【问题标题】:Merge discriminated union of object types in Typescript在 Typescript 中合并对象类型的区分联合
【发布时间】:2020-08-31 21:27:32
【问题描述】:

是否可以在对象类型的区分联合中合并所有属性?

例如,假设我有以下类型:

type UnionType = { name: string; } | { age: number; } | { visible: boolean; }

是否可以像这样将它们合并为一个类型:

// Expect: { name: string; age: number; visible: boolean };
type Props = MagicType<UnionType>;

这本质上是来自utility-typesUnionize 类型的逆。

【问题讨论】:

  • 这不是discriminated union(一个联合,其中每个成员可以通过具有不同文字值的公共属性与其他成员区分开来),它只是一个联合。您要求的是(本质上)将联合变成一个交叉点,这是this question 的副本。
  • 请注意,如果您确实以这种方式合并了一个可区分联合(例如,{type: "circle", radius: number} | {type: "square", length: number}),那么您最终会得到一个不可能的判别式类型(例如,{type: never, radius: number, length: number}

标签: typescript


【解决方案1】:

您可以使用this question 的答案将联合变成交叉点,并附带所有注意事项:

type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

如果您不喜欢 { name: string; } &amp; { age: number; } &amp; { visible: boolean; } 的外观,可以要求编译器使用标识 mapping 将其重新解释为单个对象类型:

type MagicType<U> = 
  UnionToIntersection<U> extends infer O ? { [K in keyof O]: O[K] } : never;

这将为您提供以下输出:

type Props = MagicType<UnionType>;
/* type Props = {
    name: string;
    age: number;
    visible: boolean;
} */

这就是你想要的。希望有帮助;祝你好运!

Playground link to code

【讨论】:

    猜你喜欢
    • 2020-07-30
    • 2021-09-03
    • 1970-01-01
    • 2020-05-23
    • 2022-07-20
    • 2020-05-07
    • 2020-05-03
    • 2022-06-11
    • 2017-04-10
    相关资源
    最近更新 更多