TypeScript Union Type: 可选 Key 实现技巧
2025-02-04 01:33:00
TypeScript 中 Union Type 的可选 Key 实现
在使用 TypeScript 构建类型安全的应用时,经常会遇到需要在一个联合类型(Union Type)中将某个 key 设置为可选的情况。通常是因为业务逻辑发生改变,导致某些字段不是在所有情况下都必须存在。以下介绍几种常见的方式来解决这个问题。
使用 Partial
和 Union Type 的组合
Partial<T>
是 TypeScript 提供的一个泛型类型,可以将类型 T
的所有属性变为可选。通过结合 Partial
和 Union Type,可以将指定的 key 设置为可选。
原理:
Partial
创建一个新类型,其中原始类型的所有属性都变为可选。随后,利用 Union Type 创建两种类型选择:原始类型(带必须 key)和 Partial
类型(可选 key)。
实现方式:
-
首先,定义你的 Union Type:
export type Types = "APPLE" | "MANGO" | "BANANA";
-
定义一个类型,除了你想设置为可选的 Key 外,其他的 Key 都必须存在。
type OptionalBanana
T extends "BANANA" ? T : never;
3. 定义你的 Mapping type 加上 Partial,可以这么操作。
```typescript
type MyMapping = { [key in Types]: string } & Partial<{ [K in OptionalBanana<Types>]: string }>;
const MAPPING: MyMapping = {
APPLE: "Here is Apple",
MANGO: "Here is Mango",
};
const MAPPING_BANANA: MyMapping = {
APPLE: "Here is Apple",
MANGO: "Here is Mango",
BANANA:"Here is BANANA",
};
代码示例:
使用 Omit
和 Pick
Omit<T, K>
从类型 T
中排除键 K
,Pick<T, K>
则从类型 T
中选择键 K
。可以结合两者来创建一个新的类型,使其仅在某些条件下包含特定的键。
原理:
使用 Pick
创建一个仅包含要设为可选的 key 的类型。使用 Omit
剔除这个 key 创建另一个类型。最后,将这两个类型合并为一个新的类型,该类型中指定的 key 是可选的。
实现方式:
- 定义一个类型,用来
Pick
可选的key。
type BananaType = Pick<{ [key in Types]: string }, 'BANANA'>;
- 定义一个新的Mapping Type。
type MappingWithoutBanana = Omit<{ [key in Types]: string }, 'BANANA'>
3. 合并两种Type成一个新的 Type。
```typescript
type NewMapping = MappingWithoutBanana & Partial<BananaType>;
代码示例:
export type Types = "APPLE" | "MANGO" | "BANANA";
type BananaType = Pick<{ [key in Types]: string }, 'BANANA'>;
type MappingWithoutBanana = Omit<{ [key in Types]: string }, 'BANANA'>
type NewMapping = MappingWithoutBanana & Partial<BananaType>;
const MAPPING: NewMapping = {
APPLE: "Here is Apple",
MANGO: "Here is Mango",
};
const MAPPING_BANANA: NewMapping = {
APPLE: "Here is Apple",
MANGO: "Here is Mango",
BANANA: "Here is Banana"
};
优点: 这种方法相比于直接使用 Exclude
,在一些较为复杂的类型场景下可能更容易理解和维护。它通过明确地提取和排除属性,使得类型转换的过程更为清晰。
扩展现有类型
有时候可以通过扩展现有类型来实现目的,这种方式更像是一种曲线救国的方法,适用于不方便直接修改原始 Union Type 定义的情况。
原理:
创建一个新的类型,继承自原始类型,并且将指定的 key 设置为可选。通过使用 &
运算符进行交叉类型合并。
实现方式:
-
创建一个 Type 添加 Optional BANANA。
type OptionalType = { BANANA?: string };
2. 创建一个Type继承 MAPPING 加上Optional 的值。
```typescript
type MyMapping = { [key in Types]: string } & OptionalType;
```
**代码示例:**
```typescript
export type Types = "APPLE" | "MANGO" | "BANANA";
type OptionalType = { BANANA?: string };
type MyMapping = { [key in Types]: string } & OptionalType;
const MAPPING: MyMapping = {
APPLE: "Here is Apple",
MANGO: "Here is Mango",
};
const MAPPING_BANANA: MyMapping = {
APPLE: "Here is Apple",
MANGO: "Here is Mango",
BANANA:"Here is Banana"
};
注意事项: 使用类型断言时要格外小心,确保值的实际类型与断言的类型一致,避免在运行时出现错误。如果有可能,尽量使用类型守卫或者其他更安全的方式来确保类型的正确性。
以上提供的几种方法都可以实现在 Union Type 中将 key 设置为可选的目的。具体使用哪种方式,需要根据实际的项目情况、团队的编码习惯以及对类型安全的要求来选择。