[英]Union type for generic param
代理返回条件随机类型。
const numbersArray = [1,2,3,4];
const stringsArray = ['1','2','3','4'];
function func<T>(array: T[]): T[][] {
return [[array[0], array[1]], [array[2], array[3]]];
}
const proxy = () => Math.random() < 0.5 ? numbersArray : stringsArray;
const resulNumbers = func(numbersArray);
const resultStrings = func(stringsArray);
const resultUnion = func(proxy()); // error
错误
const proxy: () => number[] | string[]
Argument of type 'number[] | string[]' is not assignable to parameter of type 'number[]'.
Type 'string[]' is not assignable to type 'number[]'.
Type 'string' is not assignable to type 'number'.(2345)
解决这个问题的正确方法,有什么想法吗?
这个 function:
const proxy = () => Math.random() < 0.5 ? numbersArray : stringsArray;
返回类型为:
number[] | string[]
这种类型表示您要么有一个所有数字的数组,要么有一个所有字符串的数组,但绝不是两者的混合。
那么该类型的成员的类型是什么? 你可能认为它是number | string
number | string
,但这并不完全正确。 如果你拿string | number
string | number
并将数组符号添加到末尾,您将获得:
(number | string)[]
这种类型表示它是一个字符串或数字数组,每个成员都可以是。 您现在可以将两者混合使用。 这不是一回事。 这意味着无法推断成员类型,因为该成员类型不能用于构造原始数组类型。
现在让我们看看通用的 function:
function func<T>(array: T[]): T[][] {
return [[array[0], array[1]], [array[2], array[3]]];
}
这个 function 试图找到数组T[]
的成员类型T
。 但如上所示, string[] | number[]
没有好的成员类型。 string[] | number[]
。 所以 typescript 无法推断T
并抛出错误。
因此,要使您的 function 工作,成员类型T
需要是可推断的。 您可以通过将代理的返回类型转换为兼容的数组类型来做到这一点,其中只有数组的成员是联合。
const proxy: () => (string | number)[] =
() => Math.random() < 0.5 ? numbersArray : stringsArray;
现在T
可以变成string | number
string | number
和一切都像你期望的那样工作。
const resultUnion = func(proxy()); // type: (string | number)[][]
发生错误是因为类型参数T
如何解析对func
的调用。 proxy
的返回类型是
number[] | string[]
并根据number[] | string[]
的方式推断T
的类型 number[] | string[]
符合以下签名:
function func<T>(x: T[]): T[][]
所以x
必须是T
的数组,就func
而言,它可以是任何类型。 在number[] | string[]
的情况下 number[] | string[]
T
的类型被推断为number
,因为number[]
是联合中第一个与x
的T[]
匹配的类型。 不幸的是,没有考虑到string[]
。
您可能希望T
是number | string
此调用的number | string
,您可以通过在调用func
时显式指定类型来做到这一点:
const xs: (number | string)[][] = func<number | string>(proxy())
这个重复的问题的答案解释了为什么 TypeScript 并不总是推断泛型类型参数的联合; 这是因为当调用者为单个泛型类型参数指定多个事物时,它通常表示错误,并且如果编译器总是在这种情况下推断出一个联合,它将允许很多可能错误的代码。 有关此问题的“官方”讨论,请参见microsoft/TypeScript#19656 。
无论如何,在您的情况下,我可能会将func()
签名更改为:
function func<T extends any[]>(array: T): T[number][][] {
return [[array[0], array[1]], [array[2], array[3]]];
}
在这种情况下, T
实际上是传入数组的类型,而不是其成员的类型,即T[number]
。 我想这应该对你有用。
希望有帮助; 祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.