你遇到过分配条件类型 https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#distributive-conditional-types:
所检查的类型是裸类型参数的条件类型被称为分配条件类型。分布式条件类型在实例化期间自动分布在联合类型上。例如,一个实例化T extends U ? X : Y
使用类型参数A | B | C
for T
被解析为(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)
所以在此:
type not_A_B_1 = A extends B ? never : A; // 'a' | 'b' | 'c'
The A
是具体类型,而不是类型参数,因此条件类型does not分配给其选民。
But in
type Not<T, U> = T extends U ? never : T;
the T
是一个裸类型参数,所以条件类型does得到分发。 “裸体”是什么意思?它的意思是T
与某些类型的函数相反T
。所以在{foo: T} extends W ? X : Y
, 类型参数T
是“穿衣”的,所以它不会分发。
这导致了一种在您不需要分配条件类型时关闭它们的方法:装饰类型参数。最简单且最不冗长的方法是使用tuple https://www.typescriptlang.org/docs/handbook/basic-types.html#tuple一个元素的:所以,
T extends U ? V : W // naked T
[T] extends [U] ? V : W // clothed T
Since [T] extends [U]
准确的时间应该是正确的T extends U
,除了分布性之外,它们是等价的。所以让我们改变一下Not<>
非分配性:
type NotNoDistribute<T, U> = [T] extends [U] ? never : T;
type not_A_B_2 = NotNoDistribute<A, B> // 'a' | 'b' | 'c'
Now not_A_B_2
是相同的not_A_B_1
。如果你更喜欢原版not_A_B_2
行为,然后使用分布式条件类型,例如Not<>
。如果您更喜欢非分配行为,请使用具体类型或固定类型参数。那有意义吗?
顺便说一下,你的Not<T,U>
类型已经作为预定义类型 https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#predefined-conditional-types在标准库中为Exclude<T,U> https://github.com/Microsoft/TypeScript/blob/v3.0.1/lib/lib.es5.d.ts#L1386-L1389,意思是“排除T
那些可分配给的类型U
".
希望有帮助。祝你好运!