【问题标题】:Extracting inner generic type of union returning unknown提取内部通用类型的联合返回未知
【发布时间】:2021-09-13 23:02:44
【问题描述】:

我正在尝试提取联合的泛型类型,但我不知道。 但是,如果我明确尝试提取(检查下面的代码),它会正确返回类型。为什么?以及如何一般地提取类型?

'use strict';

type  error = {
    tag: 'error',
    error: string
}

type success<T> = {
    tag: 'success',
    value: T
}

type Either<T> =  error | success<T>;

type extractGeneric<Type> = Type extends Either<infer X> ? X : never


type innerType = extractGeneric<Either<number>>; // type is unknown
type innerType2 = Either<number> extends Either<infer X> ? X : never; // type is number

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    这是因为innerTypedistributive conditional typeinnerType2 不是。

    这意味着他们的行为不同。

    引用distributive conditional types docs:

    如果我们将联合类型插入 ToArray,则条件类型将应用于该联合的每个成员。

    ToArray 等价于extractGeneric

    因此,extractGeneric 首先尝试从 error 获取泛型参数,然后从 success 获取。因为error 没有通用参数,所以它返回unknown。这是设计使然

    考虑这个伪代码:

    type extractGeneric<Type> = Type extends error (unknown) | Type extends success<infer X> ? X | unknown : never
    
    

    事实上,我们最终得到了X | unknown。因为unknown 的具体程度低于X 的联合X | unknown 返回unknown

    如何一般性地提取类型?

    只需使用需要泛型参数的联合部分

    type error = {
        tag: 'error',
        error: string
    }
    
    type success<T> = {
        tag: 'success',
        value: T
    }
    
    type Either<T> = error | success<T>;
    
    type extractGeneric<Type> = Type extends success<infer X> ? X : never
    
    type innerType = extractGeneric<Either<number>>; // number
    

    您可能已经注意到它不会抛出错误,因为 Either extends success

    你可以关闭分配:

    type error = {
        tag: 'error',
        error: string
    }
    
    type success<T> = {
        tag: 'success',
        value: T
    }
    
    type Either<T> = error | success<T>;
    
    type extractGeneric<Type> = [Type] extends [Either<infer X>] ? X : never
    
    type innerType = extractGeneric<Either<number>>; // number
    
    

    附:按照惯例,所有类型别名都应该大写。

    // bad
    type foo = number
    
    // good
    type Foo = number
    

    【讨论】:

      猜你喜欢
      • 2020-10-03
      • 1970-01-01
      • 2021-03-24
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      • 1970-01-01
      相关资源
      最近更新 更多