繁体   English   中英

联合泛型中的打字稿类型推理问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM