打字稿条件类型和分支缩小

Typescript conditionnal type and branch narrowing

使用此代码

type Identity <T extends string> = T;

type MaybeString = string | undefined;

type StringOrNever = MaybeString extends undefined ? never : Identity<MaybeString>;

当使用 MaybeString 作为 Identity 参数时,编译器抱怨无法将 undefined 分配给类型 String。

想知道这是否与条件类型的分配属性有关,我试了一下

type StringOrNever = [MaybeString] extends [undefined] ? [never] : Identity<MaybeString>;

这也不行。

我做错了什么?

这与分配无关。

Distributive conditional types作用于泛型StringOrNever 中的 MaybeString 不是通用的。

MaybeString extends undefined 不会缩小到 string。在这种情况下,MaybeString 仍然是 string | undefined

为了使其工作,您应该参数化 StringOrNever

看这个例子:

type Identity<T extends string> = T;

type MaybeString = string | undefined;

type StringOrNever<T extends string | undefined> = T extends string ? Identity<T> : never

type Result1 = StringOrNever<'Hello'> // hello
type Result2 = StringOrNever<undefined> // never
type Result3 = StringOrNever<undefined | 'some stirng'> // 'some string'

Playground

Result3 有一个有趣的案例。事实上,Result3 是字符串的并集,从不:"some string" | never。在这种情况下,neverstring 发生冲突。那么,你想如何处理 union ?我们可以像您一样关闭分配性

type Identity<T extends string> = T;

type MaybeString = string | undefined;

type StringOrNever<T extends string | undefined> = [T] extends [string] ? Identity<T> : never

type Result1 = StringOrNever<'Hello'> // hello
type Result2 = StringOrNever<undefined> // never
type Result3 = StringOrNever<undefined | 'some stirng'> // never