[英]Typescript type Inference problem in union generics
type SingleOrArray<T> = T | [T]
function f<T extends 'a' | 'b'>(a: SingleOrArray<T>, b: SingleOrArray<T>) {
return a && b
}
f('a', ['b'])
然后我得到了一个错误: Argument of type '"a"' is not assignable to parameter of type 'SingleOrArray<"b">'
,并且 'f' 被推断为:
function f<"b">(a: SingleOrArray<"b">, b: SingleOrArray<"b">): SingleOrArray<"b">"
我真的无法解释为什么,需要帮助!
如果这不能代表您当时尝试做的事情,那么这将无济于事,但是在示例的功能中使用泛型是没有意义的。 直接使用类型,也许先给它别名:
type AOrB = 'a' | 'b';
function f(a: SingleOrArray<AOrB>, b: SingleOrArray<AOrB>) {
return a && b
}
这样,类型在两个参数中都是独立的。 您可以在示例中通过引入另一个类型参数来解决这个问题,然后将一个用于第一个参数,一个用于第二个参数。
function f<
T1 extends 'a' | 'b',
T2 extends 'a' | 'b'
>(a: SingleOrArray<T1>, b: SingleOrArray<T2>) {
return a && b
}
在深入研究源代码一整天后,我想我得到了答案:
实际上<T>
分别从T
和[T]
推断为'a'
和'b'
,称为候选类型。 这两种候选类型具有不同的优先级:联合类型定义中的T
有一个特殊的优先级值1
(查看https://github.com/Microsoft/TypeScript/blob/master/src/compiler/types.ts ,第 4398 行, NakedTypeVariable
枚举值),而[T]
有一个共同的优先级值0
,这意味着优先级更高。
然后在比较类型详细信息之前,更高优先级的值0
将立即覆盖1
。 这就是'a'
类型被删除的原因。 如果它们共享相同的优先级值,那么它们将被合并(见下文)。
最简单的修复方法是删除<T extends 'a' | 'b'>
<T extends 'a' | 'b'>
。 没有任何断言, T
在[T]
将被推断为更宽的类型string
解构的虚拟表达后['b']
我还发现了当存在多个候选类型时编译器的处理方式:如果候选类型共享一个基本的(如字符串、数字)协变类型,则将它们与联合符号|
连接起来|
. 否则将获得最左边的类型,右边没有类型是超类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.