类型体操入门
约 574 字大约 2 分钟
TypeScript
2025-08-18
在 TypeScript 中,类型不仅能检查变量和函数,还能进行“运算”。当我们利用泛型、条件类型、映射类型等组合来推导、改造、生成新类型时,这种玩法就被戏称为 类型体操。
它听起来很高深,但其实就是 逻辑运算 + 模式匹配 + 推理。
关键语法
要学类型体操,先熟悉以下几个“积木块”:
keyof
取出对象类型的所有键,得到联合类型:
interface User { id: number; name: string; }
type Keys = keyof User; // "id" | "name"
映射类型
遍历一个对象类型的所有键,构造新类型:
type ReadonlyUser<T> = {
[K in keyof T]: T[K];
};
条件类型
根据条件决定结果:
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<123>; // false
infer
推断
在条件类型里推断出未知的类型:
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type A = GetReturnType<() => number>; // number
联合类型分发
条件类型在遇到联合类型时会自动分发:
type ToArray<T> = T extends any ? T[] : never;
type A = ToArray<"a" | "b">; // "a"[] | "b"[]
内置工具类型体操
Pick<T, K>
从 T
中选取部分键:
type MyPick<T, K extends keyof T> = {
[P in K]: T[P];
};
思路:
- 遍历
K
- 从
T
中取出对应的类型
Omit<T, K>
去掉部分键,其实就是 Pick + Exclude
:
type MyOmit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
思路:
keyof T
得到所有键- 用
Exclude
剔除掉K
- 再
Pick
出剩下的键
Awaited<T>
获取 Promise 的值:
type MyAwaited<T> = T extends Promise<infer U> ? MyAwaited<U> : T;
思路:
- 判断是不是
Promise
- 如果是,解包(
infer U
) - 递归继续解包
实战
部分只读属性
把 T
的部分属性变为只读:
type PartiallyReadonly<T, K extends keyof T> =
Omit<T, K> & { readonly [P in K]: T[P] };
interface User { id: number; name: string; }
type UserWithReadonlyId = PartiallyReadonly<User, "id">;
// { readonly id: number; name: string }
提取对象中的函数键
type FunctionKeys<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never
}[keyof T];
interface User {
id: number;
name: string;
greet(msg: string): void;
}
type FnKeys = FunctionKeys<User>; // "greet"
去掉对象中值为 never
的属性
type RemoveNever<T> = {
[K in keyof T as T[K] extends never ? never : K]: T[K];
};
type Example = RemoveNever<{ a: string; b: never; c: number }>;
// { a: string; c: number }
贡献者
更新日志
2025/8/18 03:29
查看所有更新日志
dd260
-doc update于