对不同数组类型的并集使用数组方法(例如,映射),而不要转换为any []或[]

时间:2018-12-18 04:02:49

标签: typescript

我有一个函数采用两个或多个数组类型的并集。例如。

type MyArray = string[] | number[];

const someFunc = (array: MyArray) => array.map(x => x.toString());

这是错误消息:

Cannot invoke an expression whose type lacks a call signature.
Type '
<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] |
<U>(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]
'
has no compatible call signatures.

问题:

  1. 错误消息中的expression是什么?
  2. expression的类型是什么?
  3. 我们如何指定expression的类型?

这是我尝试过的:

const someFunc01 = (array: MyArray) =>
  (array as any[]).map(x => x.toString());

const someFunc02 = <T extends MyArray, U extends T[number]>(array: U[]) =>
  array.map(x => x.toString());

const someFunc03 = (array: MyArray) =>
  (array as []).map(x => x.toString());

要清楚,这些是用例:

someFunc01([10, 20, 30]); // must compile
someFunc01(['foo', 'bar', 'baz']); // must compile
someFunc01(['foo', 10, 'baz']); // must not compile

1 个答案:

答案 0 :(得分:3)

  

错误消息中的表达式是什么?

它是array.map,您正在尝试为array中的someFunc参数调用的数组方法

  

表达式的类型是什么?

它是两种类型的并集,一种用于map()数组中的string[],另一种用于map()数组中的number[]

  

我们如何指定该表达式的类型?

type E = (string[] | number[])['map'];

playground popup

中提供此类型
type E = (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[])

这是TypeScript中的一个长期存在的问题-不允许在联合类型上调用方法,即使联合中的所有成员都具有名称相同但签名不同但适当的方法也是如此。

目前,您必须在这样的实现中使用类型断言

type StringOrNumberArrayMap = (string | number)[]['map'];

const someFunc = (array: MyArray) => (array.map as StringOrNumberArrayMap)(x => x.toString());

这不会影响someFunc的界面,您为someFunc设计的所有示例都应按预期进行编译(或不进行编译)。

此问题可能会或可能不会在编译器的下一版本(3.3或更高版本)中修复,请参见this PR