[英]Union type for generic param
The proxy return conditional randomly type.代理返回条件随机类型。
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
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)
The right way to resolve this issue, any ideas?解决这个问题的正确方法,有什么想法吗?
This function:这个 function:
const proxy = () => Math.random() < 0.5 ? numbersArray : stringsArray;
has a return type of:返回类型为:
number[] | string[]
This type says that the you either have an array of all numbers, or an array of all strings, but never a mix of both.这种类型表示您要么有一个所有数字的数组,要么有一个所有字符串的数组,但绝不是两者的混合。
So what is the type of the members of that type?那么该类型的成员的类型是什么? You might think it's
number | string
你可能认为它是
number | string
number | string
, but that's not quite true. number | string
,但这并不完全正确。 If you take string | number
如果你拿
string | number
string | number
and add the array notation to the end, you get: string | number
并将数组符号添加到末尾,您将获得:
(number | string)[]
This type says that it's an array of strings or numbers, and each member could be either.这种类型表示它是一个字符串或数字数组,每个成员都可以是。 You can now mix both.
您现在可以将两者混合使用。 This is not the same thing.
这不是一回事。 This means that the member type cannot be inferred, because that member type can't be used to construct the original array type.
这意味着无法推断成员类型,因为该成员类型不能用于构造原始数组类型。
Now lets look at the generic function:现在让我们看看通用的 function:
function func<T>(array: T[]): T[][] {
return [[array[0], array[1]], [array[2], array[3]]];
}
This function tries to find the member type T
for the array T[]
.这个 function 试图找到数组
T[]
的成员类型T
。 But as demonstrated above, there is no good member type for string[] | number[]
但如上所示,
string[] | number[]
没有好的成员类型。 string[] | number[]
. string[] | number[]
。 So typescript fails to infer T
and throws an error.所以 typescript 无法推断
T
并抛出错误。
So to make your function work, the member type T
needs to be inferable.因此,要使您的 function 工作,成员类型
T
需要是可推断的。 You can do that by casting the return type of proxy to a compatible array type where only the members of the array are a union.您可以通过将代理的返回类型转换为兼容的数组类型来做到这一点,其中只有数组的成员是联合。
const proxy: () => (string | number)[] =
() => Math.random() < 0.5 ? numbersArray : stringsArray;
Now T
can become string | number
现在
T
可以变成string | number
string | number
and everything works like you expect. string | number
和一切都像你期望的那样工作。
const resultUnion = func(proxy()); // type: (string | number)[][]
The error happens because how the type argument T
resolves for that call to func
.发生错误是因为类型参数
T
如何解析对func
的调用。 The return type of proxy
is proxy
的返回类型是
number[] | string[]
and the type for T
gets inferred based on how number[] | string[]
并根据
number[] | string[]
的方式推断T
的类型number[] | string[]
fits in the following signature: number[] | string[]
符合以下签名:
function func<T>(x: T[]): T[][]
So x
must be an array of T
s, which may be any type as far as func
is concerned.所以
x
必须是T
的数组,就func
而言,它可以是任何类型。 In the case of number[] | string[]
在
number[] | string[]
的情况下number[] | string[]
the type for T
is inferred to be number
, because number[]
is the first type in the union that matches T[]
for x
. number[] | string[]
T
的类型被推断为number
,因为number[]
是联合中第一个与x
的T[]
匹配的类型。 Unfortunately, string[]
is not taken into account.不幸的是,没有考虑到
string[]
。
You might want T
to be number | string
您可能希望
T
是number | string
number | string
for this call, and you can do that by explicitly specifying the types while calling func
:此调用的
number | string
,您可以通过在调用func
时显式指定类型来做到这一点:
const xs: (number | string)[][] = func<number | string>(proxy())
The answer to the question this duplicates explains why TypeScript doesn't always infer unions for generic type parameters; 这个重复的问题的答案解释了为什么 TypeScript 并不总是推断泛型类型参数的联合; it's because it's often indicative of an error when callers specify multiple things for a single generic type parameter, and if the compiler always inferred a union in such situations, it would allow a lot of probably-wrong code.
这是因为当调用者为单个泛型类型参数指定多个事物时,它通常表示错误,并且如果编译器总是在这种情况下推断出一个联合,它将允许很多可能错误的代码。 See microsoft/TypeScript#19656 for "official" discussion about this.
有关此问题的“官方”讨论,请参见microsoft/TypeScript#19656 。
Anyway in your case I would probably change the func()
signature to be like this:无论如何,在您的情况下,我可能会将
func()
签名更改为:
function func<T extends any[]>(array: T): T[number][][] {
return [[array[0], array[1]], [array[2], array[3]]];
}
in which case T
is actually the type of the array passed in and not of its members, which is T[number]
.在这种情况下,
T
实际上是传入数组的类型,而不是其成员的类型,即T[number]
。 That should work for you, I think.我想这应该对你有用。
Hope that helps;希望有帮助; good luck!
祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.