将标签映射到已标记的工会成员不适用于特定工会,仅适用于通用工会

时间:2019-05-04 20:17:27

标签: typescript discriminated-union

作为this answer的后续工作,我正在尝试编写一个通用类型,该通用类型将标记映射到已区分联合的一部分。

以上答案中给出的通用版本有效:

type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = T extends Record<K, V> ? T : never

但是我无法创建自己的版本,该版本在T(联合本身)上不是通用的。如果我将通用类型的联合类型设置为默认类型(我觉得很奇怪),它会正常工作。

这是我的代码:

interface TypeA {
  tag: "a";
  data: string;
}

interface TypeB {
  tag: "b";
  data: [number];
}

interface TypeCD {
  tag: "c" | "d";
  data: number;
}

type Union = TypeA | TypeB | TypeCD;

type DiscriminatedUnion_0<V extends Union["tag"]> = Union extends Record<"tag", V> ? Union : never;
let shouldBeTypeA_0: DiscriminatedUnion_0<"a">; // doesn't work, type 'never'

// this works
type DiscriminatedUnion_1<V extends Union["tag"], T extends Union = Union> = T extends Record<"tag", V> ? T : never;
let shouldBeTypeA_1: DiscriminatedUnion_1<"a">;

type DiscriminatedUnion_2<V extends Union["tag"], T extends Union> = T extends Record<"tag", V> ? T : never;
let shouldBeTypeA_2: DiscriminatedUnion_2<"a", Union>;

1 个答案:

答案 0 :(得分:1)

DiscriminateUnion中的技术使用distributive conditional type,该功能仅在检查基本的泛型类型参数时才有效。该链接对其进行了很好的解释,或者您可以根据需要阅读longer explanation。获得此行为的唯一方法是对裸通用类型参数 somewhere 进行条件处理。这就是DiscriminatedUnion_1起作用的原因;您检查了类型参数T

幸运的是,您不必使用默认类型参数玩游戏即可获得此效果。泛型类型参数检查必须进行,但不必直接在最终类型别名的 中。

一种实现方法是使用原始的DiscriminateUnion<T, K, V>定义,并创建一个使用它的别名,例如

type MyDiscriminateUnion<V extends Union["tag"]> = DiscriminateUnion<Union, "tag", V>;

不过,另一种方法是使用名为Extract<T, U>的预定义类型别名in the standard library,该别名返回与另一个类型{{1 }}。定义如下:

T

这样,您就可以构造U而不用使用默认类型参数玩游戏了:

type Extract<T, U> = T extends U ? T : never;

好的,希望能有所帮助;祝你好运!

相关问题