TypeScript 嵌套递归工具封装
嵌套递归工具类型用于处理深层对象结构,遍历所有层级进行类型转换,下面梳理核心实现。
深层 Partial
内置 Partial<T> 仅处理第一层,深层对象需递归处理:
TypeScript
type DeepPartial<T> = T extends object
? { [K in keyof T]?: DeepPartial<T[K]> }
: T;
interface Config {
database: {
host: string;
options: {
timeout: number;
};
};
}
type PartialConfig = DeepPartial<Config>;
// 等价于:
// {
// database?: {
// host?: string;
// options?: {
// timeout?: number;
// };
// };
// }
const cfg: PartialConfig = {
database: {
options: { timeout: 5000 }
}
};
深层 Readonly
TypeScript
type DeepReadonly<T> = T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
interface State {
user: {
name: string;
prefs: { theme: string };
};
}
const state: DeepReadonly<State> = {
user: { name: "Alice", prefs: { theme: "dark" } }
};
// state.user.name = "Bob"; // ❌
// state.user.prefs.theme = "light"; // ❌
深层 Required
TypeScript
type DeepRequired<T> = T extends object
? { [K in keyof T]-?: DeepRequired<T[K]> }
: T;
interface OptionalConfig {
database?: {
host?: string;
options?: {
timeout?: number;
};
};
}
type FullConfig = DeepRequired<OptionalConfig>;
// 所有层级都变为必填
深层 Pick
TypeScript
type DeepPick<T, K extends string> = K extends `${infer First}.${infer Rest}`
? First extends keyof T
? { [P in First]: DeepPick<T[First], Rest> }
: never
: K extends keyof T
? { [P in K]: T[P] }
: never;
interface User {
id: string;
profile: {
name: string;
address: {
city: string;
zip: string;
};
};
}
type UserProfile = DeepPick<User, "id" | "profile.name" | "profile.address.city">;
// {
// id: string;
// profile: {
// name: string;
// address: {
// city: string;
// };
// };
// }
深层 Omit
TypeScript
type DeepOmit<T, K extends string> = K extends `${infer First}.${infer Rest}`
? First extends keyof T
? { [P in First]: DeepOmit<T[First], Rest> } & Omit<T, First>
: T
: Omit<T, K>;
type SafeUser = DeepOmit<User, "profile.address.zip">;
// zip 字段被排除,其余保留
递归边界处理
避免无限递归(如处理数组/函数):
TypeScript
type DeepPartialSafe<T> = T extends Function | Date | RegExp
? T
: T extends Array<infer U>
? Array<DeepPartialSafe<U>>
: T extends object
? { [K in keyof T]?: DeepPartialSafe<T[K]> }
: T;
interface WithArray {
tags: { name: string; count: number }[];
createdAt: Date;
}
type PartialWithArray = DeepPartialSafe<WithArray>;
// Date 不展开,数组元素递归处理
要点总结
- 深层工具类型通过递归条件类型
T extends object ? ... : T遍历所有层级 - 映射类型
[K in keyof T]配合递归调用实现逐层转换 - 模板字面量类型
.${infer Rest}实现路径式深层操作(DeepPick/DeepOmit) - 边界处理排除函数/Date/RegExp 等内置对象,避免无限递归
- 数组需特殊处理:
T extends Array<infer U> ? Array<DeepXXX<U>> : ...
📝 发现内容有误?点击此处直接编辑