我试图将(infer R)[]
用于never
和any
类型,以解包数组。
type UnpackArrayType<T> = [T] extends [(infer R)[]] ? R : false;
但结果是出乎意料的:Typescript既没有从";否则";(非阵列条件(也无法检测推断类型R。
演示链接
type UnpackArrayType<T> = [T] extends [(infer R)[]] ? R : false; // false type used as non-array-marker
type UA<T> = UnpackArrayType<T>; // just alias
type TypeTesting = {
"never": UA<never>, // unknown - incorrect
"never[]": UA<never[]>, // never - correct
"any": UA<any>, // unknown - incorrect
"any[]": UA<any[]>, // any - correct
"unknown": UA<unknown>, // false - correct
"unknown[]": UA<unknown[]>, // unknown - correct
"null": UA<null>, // false - correct
"null[]": UA<null[]>, // null - correct
"undefined": UA<undefined>, // false - correct
"undefined[]": UA<undefined[]>, // undefined - correct
"number": UA<number>, // false - correct
"number[]": UA<number[]>, // number - correct
}
为什么any
和never
类型拆包为unknown
?
extends
测试类型之间的关系,然后尝试提取推断的位置。
any
和never
都具有它们是任何其他类型的子类型的性质(any
更奇怪,因为它也是任何其他类型中的基类型(。因此,对于任何类型的T
,询问问题never extends T
或any extends T
都将返回true。
在回答了扩展问题之后,我们可以考虑推理问题吗?由于没有好的方法从any
或never
中提取[(infer R)[]]
中的R
,因此最终得到unknown
。
您可以对这两种通用类型的子类型进行特殊处理:
type UnpackArrayType<T> =
[T] extends [never] ? false: // nothing extends never except never itslef
[T & 1] extends [T & 2]? false : // T & 1 extends T & 2 will only be true if T is any and the & 1 and & 2 get absorbed into any
[T] extends [(infer R)[]] ? R : false; // false type used as non-array-marker
type UA<T> = UnpackArrayType<T>; // just alias
type TypeTesting = {
"never": UA<never>, // false - correct
"never[]": UA<never[]>, // never - correct
"any": UA<any>, // false - correct
"any[]": UA<any[]>, // any - correct
"unknown": UA<unknown>, // false - correct
"unknown[]": UA<unknown[]>, // unknown - correct
"null": UA<null>, // false - correct
"null[]": UA<null[]>, // null - correct
"undefined": UA<undefined>, // false - correct
"undefined[]": UA<undefined[]>, // undefined - correct
"number": UA<number>, // false - correct
"number[]": UA<number[]>, // number - correct
}
游乐场链接
注意:要从已知为数组的类型中提取元素类型,也可以使用T[number]