【问题标题】:How to map over union array type?如何映射联合数组类型?
【发布时间】:2021-08-16 19:42:22
【问题描述】:

我有以下结构:

interface Test1 {
    number: number;
}
interface Test2 extends Test1 {
    text: string;
}

let test: Test1[] | Test2[] = [];
test.map(obj => {}); // does not work

我收到错误:

无法调用类型缺少调用签名的表达式。类型 '{ (this: [Test1, Test1, Test1, Test1, Test1], callbackfn: (this: void, value: Test1, index: nu...') 没有兼容的调用签名

我如何map 覆盖测试变量?

【问题讨论】:

标签: typescript union-types


【解决方案1】:

为 4.2 编辑

map 现在可以调用了,但您仍然需要对其参数进行显式类型注释以使其按预期工作(类型参数没有上下文类型)

let test: Test1[] | Test2[] = [];
test.map((obj: Test1 | Test2) => {});

Playground Link

这种情况可能会在未来的版本中得到改善,使得这个答案大部分已经过时(请参阅PR,它将正确合成参数的上下文类型)

4.2 之前的原始答案

问题在于,对于联合类型,作为函数的成员也将被键入为联合类型,因此 map 的类型将是 (<U>(callbackfn: (value: Test1, index: number, array: Test1[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: Test2, index: number, array: Test2[]) => U) 就打字稿而言这是不可调用的。

您可以声明Test1Test2 的并集数组

let test: (Test1 | Test2)[] = [];
test.map(obj => {}); 

或者你可以在调用时使用类型断言:

let test: Test1[] | Test2[] = [];
(test as Array<Test1|Test2>).map(o=> {});

【讨论】:

  • Array&lt;Test1|Test2&gt; 是否表明数组可能填充了两种类型的组合?所以它可能是[Test1, Test1, Test2, Test1, Test2, ...]。其中(Test1 | Test2)[]Test1[] | Test2[] 将全部为Test1 或全部Test2
  • @mtpultz Array&lt;Test1|Test2&gt;(Test1 | Test2)[] 相同,表示[Test1, Test1, Test2, Test1, Test2, ...]Test1[] | Test2[] 表示所有项目将是Test1 或所有Test2
  • @RanLottem 因为原始帖子 TS 改变了它允许此类调用的方式。由于泛型类型参数,Map 仍然不可调用。 every 没有泛型类型参数,因此 TS 可以创建可调用的合并版本。这是相关公关:github.com/Microsoft/TypeScript/pull/29011
  • 参见 TS3.3 中的 Improved behavior for calling union types 以及解释为什么 map() 仍然不起作用的 caveats
  • 看起来microsoft/TypeScript#42620合并到TS4.3终于解决了这个问题(至少如果你使用--noImplicitAny,这很奇怪)
猜你喜欢
  • 2021-06-28
  • 2019-01-12
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 2019-04-20
  • 2019-12-11
相关资源
最近更新 更多