提取返回未知的联合的内部通用类型

Extracting inner generic type of union returning unknown

我正在尝试提取联合的通用类型,但我不知道。 但是,如果我明确尝试提取(检查下面的代码),它 returns 类型正确。为什么?我如何提取通用类型?

'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

这是因为 innerTypedistributive conditional typeinnerType2 不是。

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

引自 distributive conditional types 文档:

If we plug a union type into ToArray, then the conditional type will be applied to each member of that union.

ToArray 等同于 extractGeneric

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

考虑这个伪代码:

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

事实上我们最终得到 X | unknown。因为 unknown 不如 X 联合 X | unknown returns unknown.

How can I extract the type generically?

只需使用需要泛型参数的 union 的一部分

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 扩展了 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

P.S。按照惯例,所有类型别名都应大写。

// bad
type foo = number

// good
type Foo = number