TypeScript 自定义复杂工具类型
组合条件类型与映射类型可封装业务专用工具类型,下面梳理核心用法。
条件类型
基本语法 T extends U ? X : Y:
TypeScript
type IsString<T> = T extends string ? "yes" : "no";
type A = IsString<string>; // "yes"
type B = IsString<number>; // "no"
提取返回类型
TypeScript
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
function getUser() { return { id: 1, name: "Alice" }; }
type User = ReturnType<typeof getUser>;
// { id: number; name: string; }
映射类型
使用 in 遍历联合类型生成新对象类型:
TypeScript
type Options<T> = {
[K in keyof T]?: T[K];
};
interface Config { host: string; port: number; }
type PartialConfig = Options<Config>;
// { host?: string; port?: number; }
键名映射
TypeScript
type Mutable<T> = {
-readonly [K in keyof T]: T[K];
};
type Optional<T> = {
[K in keyof T]-?: T[K]; // -? 移除可选
};
键名重映射
TypeScript
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface Person { name: string; age: number; }
type LazyPerson = Getters<Person>;
// { getName(): string; getAge(): number; }
组合条件与映射
过滤属性类型
TypeScript
type PickByType<T, U> = {
[K in keyof T as T[K] extends U ? K : never]: T[K];
};
interface Mixed {
name: string;
age: number;
active: boolean;
count: number;
}
type NumberFields = PickByType<Mixed, number>;
// { age: number; count: number; }
可选与必填转换
TypeScript
type RequiredExcept<T, K extends keyof T> = Required<Omit<T, K>> & Pick<Partial<T>, K>;
interface Config {
host: string;
port?: number;
timeout?: number;
}
// host 必填,port/timeout 可选
type Config2 = RequiredExcept<Config, "port" | "timeout">;
深层类型替换
TypeScript
type ReplaceType<T, From, To> = {
[K in keyof T]: T[K] extends From ? To : T[K];
};
interface User {
id: number;
createdAt: Date;
updatedAt: Date;
}
type StringDates = ReplaceType<User, Date, string>;
// { id: number; createdAt: string; updatedAt: string; }
实用工具类型封装
深度合并类型
TypeScript
type DeepMerge<T, U> = {
[K in keyof T | keyof U]: K extends keyof T
? K extends keyof U
? T[K] extends object
? U[K] extends object
? DeepMerge<T[K], U[K]>
: U[K]
: U[K]
: T[K]
: K extends keyof U
? U[K]
: never;
};
type A = { a: string; nested: { x: number } };
type B = { b: number; nested: { y: string } };
type Merged = DeepMerge<A, B>;
// { a: string; b: number; nested: { x: number; y: string } }
函数参数提取
TypeScript
type FirstParam<T extends (...args: any[]) => any> =
T extends (arg: infer P, ...args: any[]) => any ? P : never;
type Fn = (name: string, age: number) => void;
type Name = FirstParam<Fn>; // string
要点总结
- 条件类型
T extends U ? X : Y实现类型分支判断 - 映射类型
[K in keyof T]遍历对象键生成新类型 - 键名重映射
as语法转换键名格式 - 条件与映射组合可实现属性过滤/类型替换/深度合并
infer关键字在条件类型中推断并提取类型
📝 发现内容有误?点击此处直接编辑