【问题标题】:Why this CustomExtract returns an different result from default Extract?为什么此 CustomExtract 返回与默认提取不同的结果?
【发布时间】:2021-01-22 18:45:42
【问题描述】:

代码解释了我的问题:

type A = {
  a: number,
} | null

// Extract as defined in lib.es5.d.ts
type Extract<T, U> = T extends U ? T : never;

type CustomExtract = A extends null ? A : never;

type Result1 = Extract<A, null> // null
type Result2 = CustomExtract;   // never

Extract 和 CustomExtract 是相同的代码,区别在于 Extract 是泛型类型。

另外,作为相关示例,string | null 不扩展 null

那么,在这个主题中,类型是如何真正发挥作用的呢?我可以想象它可能会为每种联合类型运行泛型类型,然后合并所有结果,但我想要真正的技术定义和它的工作。

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    区别在于Extractdistributive conditional type,而您的CustomExtract 不是。

    为了使X extends Y ? A : B 形式的条件类型可分配,检查类型X 必须是“裸类型参数”;也就是说,type parameter 类似于 interface Foo&lt;T&gt; {...} 中的 T,而 naked 因为它只是被检查的类型参数(即T extends ...)而不是只是一些包含类型参数的表达式(例如,Promise&lt;T&gt; extends ...[T] extends ...)。

    正如您所推测的,分布式条件类型确实评估为检查类型T 的每个联合元素的条件的联合。所以如果F&lt;T&gt; 是一个分布式条件类型,那么F&lt;A | B | C&gt; 将被评估为F&lt;A&gt; | F&lt;B&gt; | F&lt;C&gt;。一个潜在的问题是F&lt;never&gt; 将被评估为never,无论F 的细节是什么(只要它是可分配的),因为never 被认为是"empty union type"

    如需更多信息,请参阅我的other answer,了解什么是分布式条件类型以及它们如何工作。

    【讨论】:

      【解决方案2】:

      @jcalz 所说的都是正确的,但我会试着用简单的英语表达。

      Extract&lt;T, U&gt; 所做的是返回T子集,它可以分配给U。如果T 有一些U 类型和一些其他类型,我们只得到U 类型。尽管有一个看起来与CustomExtract 相同的定义,但它为什么以及如何做到这一点,这就是@jcalz 的答案。

      在您的情况下,type A{a: number}null 的联合。 {a: number} 不可分配给null,但null 可分配给null。所以可分配给null 的子集是null

      type CustomExtract = A extends null ? A : never; 永远不会返回子集。如果满足条件,则返回完整的A,如果不满足条件,则返回never

      为了使X extends Y 为真,X 的所有值都必须可分配给Y,换句话说,X 必须等于或小于Y

      A extends null 为假,因为Anull 更宽。另一方面,null extends A 是真的。

      【讨论】:

        猜你喜欢
        • 2023-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多