📜  typescript 合并联合类型道具 - TypeScript (1)

📅  最后修改于: 2023-12-03 14:48:05.007000             🧑  作者: Mango

TypeScript 合并联合类型道具

在 TypeScript 中,我们可以使用联合类型来表示具有多种可能类型的值。但是,当我们需要将这些类型的道具合并到一个新的类型中时,就需要使用到合并联合类型道具的技巧。

问题描述

假设我们有以下两个联合类型:

type Foo = {
  type: 'foo';
  fooProp: string;
}

type Bar = {
  type: 'bar';
  barProp: number;
}

type MyType = Foo | Bar;

我们希望创建一个新的类型,它具有 FooBar 类型的所有道具,如下所示:

type MyCombinedType = {
  type: 'foo' | 'bar';
  fooProp?: string;
  barProp?: number;
}
解决方案

为了实现这个目标,我们可以使用交叉类型(&)和条件类型(extends)的组合。

首先,我们定义一个条件类型 ExtractProps<T, U>,以从类型 T 中提取所有道具名为 type 或在联合类型 U 中出现的道具类型。

type ExtractProps<T, U> = T extends infer O // 使用 infer 关键字提取类型变量 O
  ? O extends any // 如果类型变量 O 包含任意道具
    ? U extends O['type'] // 如果联合类型 U 中包含道具名为 type 的道具类型
      ? Pick<O, 'type'> & Partial<Omit<O, 'type'>> // 提取 type 道具并使用 Partial 将基础道具转换为可选
      : never // 否则返回 never 类型
    : never
  : never;

然后,我们可以使用交叉类型和 ExtractProps 来创建新类型 MyCombinedType

type MyCombinedType = ExtractProps<Foo, MyType> & ExtractProps<Bar, MyType>;
排版提示

在 Markdown 中,需要在代码块前面加上三个反引号和语言名,才能正确显示代码。比如:

```javascript
console.log("Hello, world!");
```

可以显示为:

console.log("Hello, world!");

因此,为了在 Markdown 中显示 TypeScript 代码,需要将代码片段以以下方式包装:

```typescript
// TypeScript 代码
```
完整代码

最终的完整代码如下:

type Foo = {
  type: 'foo';
  fooProp: string;
}

type Bar = {
  type: 'bar';
  barProp: number;
}

type MyType = Foo | Bar;

type ExtractProps<T, U> = T extends infer O
  ? O extends any
    ? U extends O['type']
      ? Pick<O, 'type'> & Partial<Omit<O, 'type'>>
      : never
    : never
  : never;

type MyCombinedType = ExtractProps<Foo, MyType> & ExtractProps<Bar, MyType>;