推断出的never[]和any[]的Typescript UnpackArrayType工作不正确



我试图将(infer R)[]用于neverany类型,以解包数组。

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
}

为什么anynever类型拆包为unknown

extends测试类型之间的关系,然后尝试提取推断的位置。

anynever都具有它们是任何其他类型的子类型的性质(any更奇怪,因为它也是任何其他类型中的基类型(。因此,对于任何类型的T,询问问题never extends Tany extends T都将返回true。

在回答了扩展问题之后,我们可以考虑推理问题吗?由于没有好的方法从anynever中提取[(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]

最新更新