TypeScript:从有区别的联合派生地图

bin*_*les 5 discriminated-union typescript

我有一个区别的联合类型,它根据字符串文字字段区分类型.我想派生一个映射类型,它将联合中的所有类型映射到它们对应的鉴别器文字值.

例如

export type Fetch = {
    type: 'fetch',
    dataType: string
};

export type Fetched<T> = {
    type: 'fetched',
    value: T
};

// union type discriminated on 'type' property
export type Action =
    | Fetch
    | Fetched<Product>;

// This produces a type 'fetch' | 'fetched'
// from the type 
type Actions = Action['type'];

// I want to produce a map type of the discriminator values to the types 
// comprising the union type but in an automated fashion similar to how I
// derived my Actions type.
// e.g.
type WhatIWant = {
    fetch: Fetch,
    fetched: Fetched<Product>
}
Run Code Online (Sandbox Code Playgroud)

这在TypeScript中是否可行?

jca*_*alz 12

通过在TypeScript 2.8中引入条件类型,您可以定义一个类型函数,在给定区分联合以及判别式的键和值的情况下,它会生成联合的单个相关组成部分:

type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = 
  T extends Record<K, V> ? T : never
Run Code Online (Sandbox Code Playgroud)

如果您想使用它来构建地图,您也可以这样做:

type MapDiscriminatedUnion<T extends Record<K, string>, K extends keyof T> =
  { [V in T[K]]: DiscriminateUnion<T, K, V> };
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,

type WhatIWant = MapDiscriminatedUnion<Action, 'type'>;
Run Code Online (Sandbox Code Playgroud)

如果你检查它,它是:

type WhatIWant = {
  fetch: {
    type: "fetch";
    dataType: string;
  };
  fetched: {
    type: "fetched";
    value: Product;
  };
}
Run Code Online (Sandbox Code Playgroud)

我认为,按照需要.希望有所帮助; 祝好运!