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

Typescript UnpackArrayType for inferred never[] and any[] works incorrectly

我正在尝试使用 (infer R)[] 作为 neverany 类型来解包数组。

type UnpackArrayType<T> = [T] extends [(infer R)[]] ? R : false;

但结果出乎意料:Typescript 既没有从“else”(非数组条件)中转换为 false,也没有检测到推断类型 R。

demo link

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 更奇怪,因为它也是任何类型的基类型其他类型)。所以问 never extends Tany extends T 的问题对于任何类型 T 都将 return 为真。

回答完扩展问题后,我们可以考虑推理问题,因为没有好的方法从 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
}

Playground Link

注意:要从已知为数组的类型中提取元素类型,您还可以使用 T[number]