TypeScript 工具类型
·
文章目录
TypeScript 工具类型
概述
TypeScript 工具类型是提高开发效率和代码质量的强大工具:
- 减少重复代码 :避免重复定义相似的类型
- 提高类型安全性 :通过类型转换和约束,减少运行时错误
- 增强代码可读性 :更清晰地表达类型意图
- 提高开发效率 :快速生成复杂类型,减少手动编写
用法
Partial
将类型 T 的所有属性变为可选
interface User {
id: number;
name: string;
email: string;
}
// 所有属性变为可选
type PartialUser = Partial<User>;
// 等价于:{ id?: number; name?: string; email?: string; }
// 使用示例
const updateUser: PartialUser = { name: "张三" };
Required
将类型 T 的所有属性变为必填
interface Config {
url?: string;
timeout?: number;
headers?: Record<string, string>;
}
// 所有属性变为必填
type RequiredConfig = Required<Config>;
// 等价于:{ url: string; timeout: number; headers: Record<string, string>; }
// 使用示例
const config: RequiredConfig = {
url: "https://api.example.com",
timeout: 5000,
headers: { "Content-Type": "application/json" }
};
Readonly
将类型 T 的所有属性变为只读
interface User {
id: number;
name: string;
}
// 所有属性变为只读
type ReadonlyUser = Readonly<User>;
// 等价于:{ readonly id: number; readonly name: string; }
// 使用示例
const user: ReadonlyUser = { id: 1, name: "张三" };
user.name = "李四"; // 编译错误:无法分配到 "name" ,因为它是只读属性
Pick
从类型 T 中选取指定的属性 K 组成新类型
interface User {
id: number;
name: string;
email: string;
password: string;
}
// 只选取 id 和 name 属性
type UserInfo = Pick<User, "id" | "name">;
// 等价于:{ id: number; name: string; }
// 使用示例
const userInfo: UserInfo = { id: 1, name: "张三" };
Omit
从类型 T 中排除指定的属性 K 组成新类型
interface User {
id: number;
name: string;
email: string;
password: string;
}
// 排除 password 属性
type PublicUser = Omit<User, "password">;
// 等价于:{ id: number; name: string; email: string; }
// 使用示例
const publicUser: PublicUser = { id: 1, name: "张三", email: "zhangsan@example.com" };
Exclude
从联合类型 T 中排除可以赋值给 U 的类型
type Animal = "cat" | "dog" | "bird" | "fish";
// 排除 "bird" 和 "fish"
type Mammal = Exclude<Animal, "bird" | "fish">;
// 等价于:"cat" | "dog"
// 使用示例
const pet: Mammal = "cat"; // 合法
const pet2: Mammal = "bird"; // 编译错误
Extract
从联合类型 T 中提取可以赋值给 U 的类型
type Animal = "cat" | "dog" | "bird" | "fish";
// 提取 "bird" 和 "fish"
type Aquatic = Extract<Animal, "bird" | "fish">;
// 等价于:"bird" | "fish"
// 使用示例
const aquaticPet: Aquatic = "fish"; // 合法
const aquaticPet2: Aquatic = "cat"; // 编译错误
NonNullable
从类型 T 中排除 null 和 undefined
type Value = string | number | null | undefined;
// 排除 null 和 undefined
type NonNullValue = NonNullable<Value>;
// 等价于:string | number
// 使用示例
const value: NonNullValue = "hello"; // 合法
const value2: NonNullValue = null; // 编译错误
ReturnType
获取函数类型 T 的返回值类型
function getUser() {
return { id: 1, name: "张三", email: "zhangsan@example.com" };
}
// 获取函数返回值类型
type User = ReturnType<typeof getUser>;
// 等价于:{ id: number; name: string; email: string; }
// 使用示例
const user: User = { id: 2, name: "李四", email: "lisi@example.com" };
Parameters
获取函数类型 T 的参数类型组成的元组
function createUser(name: string, email: string) {
return { id: Date.now(), name, email };
}
// 获取函数参数类型
type CreateUserParams = Parameters<typeof createUser>;
// 等价于:[name: string, email: string]
// 使用示例
const params: CreateUserParams = ["王五", "wangwu@example.com"];
const user = createUser(...params);
ConstructorParameters
获取类构造函数的参数类型组成的元组
class User {
constructor(public name: string, public email: string) {}
}
// 获取构造函数参数类型
type UserConstructorParams = ConstructorParameters<typeof User>;
// 等价于:[name: string, email: string]
// 使用示例
const params: UserConstructorParams = ["赵六", "zhaoliu@example.com"];
const user = new User(...params);
InstanceType
获取类构造函数的实例类型
class User {
constructor(public name: string, public email: string) {}
}
// 获取实例类型
type UserInstance = InstanceType<typeof User>;
// 等价于:User
// 使用示例
const user: UserInstance = new User("孙七", "sunqi@example.com");
Record
创建一个以 K 为键, T 为值的映射类型
// 创建字符串到数字的映射
type StringToNumber = Record<string, number>;
// 等价于:{ [key: string]: number }
// 使用示例
const scores: StringToNumber = {
"张三": 90,
"李四": 85,
"王五": 95
};
// 更具体的键类型
type UserRole = "admin" | "user" | "guest";
type RolePermissions = Record<UserRole, string[]>;
const permissions: RolePermissions = {
admin: ["read", "write", "delete"],
user: ["read", "write"],
guest: ["read"]
};
ThisType
指定对象字面量中 this 的类型
// 定义 this 类型
interface Context {
name: string;
age: number;
}
// 创建带有 this 上下文的方法集合
const methods: {
greet(): string;
getInfo(): string;
} & ThisType<Context> = {
greet() {
return `Hello, my name is ${this.name}`; // this 类型为 Context
},
getInfo() {
return `${this.name} is ${this.age} years old`; // this 类型为 Context
}
};
// 使用示例
const context: Context = { name: "张三", age: 30 };
const boundGreet = methods.greet.bind(context);
console.log(boundGreet()); // 输出:Hello, my name is 张三
DeepPartial
递归将类型 T 的所有属性(包括嵌套属性)变为可选
type DeepPartial<T> = T extends object
? { [K in keyof T]?: DeepPartial<T[K]> }
: T;
// 使用示例
interface User {
id: number;
name: string;
address: {
street: string;
city: string;
zipCode: string;
};
}
type DeepPartialUser = DeepPartial<User>;
// 所有属性(包括嵌套的 address)都变为可选
const update: DeepPartialUser = {
address: {
city: "北京"
}
};
DeepReadonly
递归将类型 T 的所有属性(包括嵌套属性)变为只读
type DeepReadonly<T> = T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
// 使用示例
interface Config {
api: {
url: string;
timeout: number;
headers: {
"Content-Type": string;
};
};
}
type DeepReadonlyConfig = DeepReadonly<Config>;
// 所有属性(包括嵌套的 api 和 headers)都变为只读
const config: DeepReadonlyConfig = {
api: {
url: "https://api.example.com",
timeout: 5000,
headers: {
"Content-Type": "application/json"
}
}
};
config.api.url = "https://new-api.example.com"; // 编译错误:无法修改只读属性
Intersection<T, U>
获取两个类型的交集
type Intersection<T, U> = {
[K in Extract<keyof T, keyof U>]: T[K] & U[K];
};
// 使用示例
interface A {
id: number;
name: string;
age: number;
}
interface B {
id: string;
name: string;
email: string;
}
type ABIntersection = Intersection<A, B>;
// 等价于:{ id: number & string; name: string & string; }
// 实际结果:{ id: never; name: string; }(因为 number & string 是 never)
更多推荐



所有评论(0)