TypeScript Omit用法全解:语法与示例 – wiki基地

TypeScript Omit 用法全解:语法与示例

在 TypeScript 的类型体操世界中,Omit 是一个非常实用的工具类型,它允许我们从一个已有的接口或类型中,“剔除” 指定的属性,从而创建一个新的类型。这种能力在处理复杂类型、构建可复用类型以及进行类型推断时非常有用。本文将深入探讨 Omit 的语法、使用场景、常见示例以及一些高级技巧,帮助你全面掌握这个强大的工具。

1. Omit 的语法与基本用法

1.1 语法定义

Omit 的类型定义如下:

typescript
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

让我们逐步解析这个定义:

  • T: 这是我们要从中剔除属性的原始类型。
  • K extends keyof any: 这是我们要剔除的属性键的联合类型。keyof any 实际上是 string | number | symbol,这意味着 K 必须是字符串、数字或符号的联合类型,也就是合法的键类型。
  • keyof T: 获取类型 T 的所有键的联合类型。
  • Exclude<keyof T, K>: Exclude 是 TypeScript 的另一个内置工具类型。它从 keyof T (所有键的联合类型) 中排除掉 K (要剔除的键的联合类型),得到剩余键的联合类型。
  • Pick<T, Exclude<keyof T, K>>: Pick 也是 TypeScript 的内置工具类型。它从 T 中选取 Exclude<keyof T, K> (剩余键的联合类型) 所指定的那些键,构建出一个新的类型。

总的来说,Omit 的工作原理是:先获取原始类型的所有键,然后排除掉要剔除的键,最后从原始类型中选取剩余的键来构建新类型。

1.2 基本示例

假设我们有一个表示用户的接口:

typescript
interface User {
id: number;
name: string;
email: string;
age: number;
}

现在,我们想创建一个不包含 emailage 属性的新类型:

“`typescript
type UserWithoutContactInfo = Omit;

// UserWithoutContactInfo 的类型等价于:
// {
// id: number;
// name: string;
// }

const user: UserWithoutContactInfo = {
id: 1,
name: ‘John Doe’,
};

// 以下代码会报错,因为 UserWithoutContactInfo 类型中没有 email 和 age 属性
// user.email = ‘[email protected]’;
// user.age = 30;
“`

在这个例子中,Omit<User, 'email' | 'age'>User 类型中剔除了 'email''age' 两个属性,创建了一个新的类型 UserWithoutContactInfo,它只包含 idname 属性。

2. Omit 的常见使用场景

Omit 在各种场景下都非常有用,以下是一些常见的例子:

2.1 创建部分更新类型

在处理数据更新时,我们通常不需要提供对象的所有属性。Omit 可以帮助我们创建一个只包含需要更新的属性的类型。

“`typescript
interface Product {
id: number;
name: string;
description: string;
price: number;
stock: number;
}

// 创建一个用于更新产品信息的类型,不需要提供 id 和 stock
type UpdateProductInfo = Omit;

function updateProduct(productId: number, updates: UpdateProductInfo) {
// … 更新产品信息的逻辑
}
const productInfo: Product = {
id:12,
name:”Apple”,
description:”test”,
price: 122,
stock: 100
}
updateProduct(productInfo.id, { name: ‘New Product Name’, price: 99.99 });
“`
在updateProduct这个例子中,id不允许修改,stock也不允许修改。

2.2 构建可复用类型

Omit 可以与其他类型操作结合,构建出更复杂、更具可复用性的类型。

“`typescript
interface BaseEntity {
id: number;
createdAt: Date;
updatedAt: Date;
}

// 从 BaseEntity 中剔除 createdAt 和 updatedAt,创建一个用于创建新实体的类型
type CreateEntity = Omit;

// 从 BaseEntity 中剔除 id,创建一个用于更新实体的类型
type UpdateEntity = Omit;
“`

2.3 简化复杂类型

当处理具有大量属性的复杂类型时,Omit 可以帮助我们专注于我们关心的部分。

“`typescript
interface ApiResponse {
data: any;
status: number;
statusText: string;
headers: any;
config: any;
request: any;
}

// 从 ApiResponse 中剔除一些我们不关心的属性
type SimplifiedApiResponse = Omit;
“`

2.4 与泛型结合使用

Omit 可以与泛型结合使用,创建更通用的类型工具。

“`typescript
// 创建一个从对象类型 T 中剔除指定键 K 的函数
function omitProps(obj: T, keys: K[]): Omit {
const result: any = {};
for (const key in obj) {
if (!keys.includes(key as any)) {
result[key] = obj[key];
}
}
return result;
}

const user = {
id: 1,
name: ‘John Doe’,
email: ‘[email protected]’,
age: 30,
};

const userWithoutEmail = omitProps(user, [’email’]);
// userWithoutEmail 的类型为 { id: number; name: string; age: number; }
“`

3. Omit 的高级技巧与注意事项

3.1 Omit 与可选属性

当原始类型包含可选属性时,Omit 的行为与预期一致:

“`typescript
interface Person {
name: string;
age?: number;
address?: string;
}

type PersonWithoutAddress = Omit;

// PersonWithoutAddress 的类型为:
// {
// name: string;
// age?: number;
// }
“`

Omit 会正确地保留可选属性的 ? 修饰符。

3.2 Omit 与联合类型

Omit 也可以用于联合类型,但结果可能与你想象的略有不同:

“`typescript
type A = { a: number; b: string };
type B = { a: number; c: boolean };
type UnionType = A | B;

type OmittedUnion = Omit;

// OmittedUnion 的类型为:
// {
// b: string;
// } | {
// c: boolean;
// }
“`
在这个例子中, OmittedUnion类型为{b: string;} | {c:boolean;}
注意:如果A类型为{ a: number; b: string; c:boolean }, 那么OmittedUnion类型为{b:string, c:boolean}

Omit 会分别应用于联合类型的每个成员,然后将结果重新组合成一个联合类型。

3.3 Omit 与交叉类型

Omit 用于交叉类型时,它的行为类似于从合并后的类型中剔除属性:

“`typescript
type C = { x: number; y: string };
type D = { y: string; z: boolean };
type IntersectionType = C & D;

type OmittedIntersection = Omit;
// OmittedIntersection 的类型为:
// {
// x: number;
// z: boolean;
// }
“`

在这个例子中,IntersectionType 实际上等价于 { x: number; y: string; z: boolean },因此 Omit<IntersectionType, 'y'> 的结果是 { x: number; z: boolean }

3.4 Omit 的替代方案 (TypeScript 4.5+)

从 TypeScript 4.5 开始,你可以使用 as 子句在映射类型中过滤键,这提供了一种更简洁的方式来实现 Omit 的效果:

“`typescript
type Omit = {

};
“`

这种写法利用了 as 子句的条件类型判断,如果键 P 属于要剔除的键 K,则将其映射为 never 类型(表示不存在),否则保留原样。

3.5 Omit 与 Record

Record 是 TypeScript 中的一个工具类型,用于创建具有特定键和值的对象类型。 Omit 可以与 Record 结合使用,以创建更复杂的类型。
“`typescript
type Fruit = ‘apple’ | ‘banana’ | ‘orange’;
type FruitPrices = Record;
const prices: FruitPrices = {
apple: 1,
banana: 2,
orange: 3
}

type AvailableFruit = Omit
const available: AvailableFruit = {
apple: 1,
orange: 3
}
“`
在这个例子中,AvailableFruit类型不能包含banana属性。

4. 总结

Omit 是 TypeScript 中一个非常强大且实用的工具类型,它可以帮助我们从现有类型中剔除指定的属性,创建新的类型。通过掌握 Omit 的语法、使用场景、高级技巧和注意事项,我们可以更好地利用 TypeScript 的类型系统,编写出更健壮、更易于维护的代码。

希望这篇文章能够帮助你深入理解 TypeScript 中的 Omit 类型,并在你的实际开发中发挥它的作用。记住,类型体操的精髓在于灵活运用各种工具类型,组合出满足特定需求的类型,Omit 只是众多工具中的一个,但它绝对是你工具箱中不可或缺的一员。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部