【问题标题】:TypeScript: derive map from discriminated unionTypeScript:从有区别的联合派生地图
【发布时间】:2018-10-12 01:07:42
【问题描述】:

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

例如

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>
}

这在 TypeScript 中可行吗?

【问题讨论】:

标签: typescript discriminated-union


【解决方案1】:

通过在 TypeScript 2.8 中引入conditional types,您可以定义一个类型函数,给定一个可区分的联合以及判别式的键和值,生成联合的单个相关成分:

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

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

type MapDiscriminatedUnion<T extends Record<K, string>, K extends keyof T> =
  { [V in T[K]]: DiscriminateUnion<T, K, V> };

所以在你的情况下,

type WhatIWant = MapDiscriminatedUnion<Action, 'type'>;

如果你检查它,它是:

type WhatIWant = {
  fetch: {
    type: "fetch";
    dataType: string;
  };
  fetched: {
    type: "fetched";
    value: Product;
  };
}

我想,如你所愿。希望有帮助;祝你好运!

【讨论】:

  • 对此的跟进:我尝试在不使用通用联合类型的情况下编写相同类型的 DiscriminateUnion —— 即,对于特定的联合类型。但是,如果不指定一些T extends MyUnionType,它就不起作用。知道为什么吗?一个最小的例子:``` ```
  • 这个例子太小了,里面什么都没有。您的问题的答案可能是该技术使用distributive conditional type,它仅在您检查裸泛型类型参数时才有效。当然,您可以使用通用版本并创建一个插入特定类型的新类型别名。如果您需要更多帮助,也许您应该提出一个新问题;一年前的答案上的 cmets 并不是发布代码和关注您的问题的最佳场所。祝你好运!
  • 这个答案太棒了。谢谢
猜你喜欢
  • 2021-10-06
  • 1970-01-01
  • 2020-09-08
  • 2017-10-03
  • 1970-01-01
  • 2021-02-14
  • 2020-04-14
  • 1970-01-01
  • 2018-11-24
相关资源
最近更新 更多