10. 类型映射
约 595 字大约 2 分钟
2025-06-02
在 TypeScript 中,类型映射可以结合条件类型实现属性过滤,这是构建复杂类型系统的强大工具。以下是几种常见的属性过滤方式:
一、基础映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
二、基于属性名过滤
1、保留指定属性
// 保留指定属性
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
// 使用示例
type User = {
id: number;
name: string;
age: number;
};
type UserName = Pick<User, "name">; // { name: string }
2、排除指定属性
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
// 使用示例
type User = {
id: number;
name: string;
age: number;
};
type UserWithoutAge = Omit<User, "age">; // { id: number; name: string }
3、保留特定前缀开头的属性
type FilterKeys<T, U extends string> = {
[K in keyof T as K extends `${U}${string}` ? K : never]: T[K];
};
// 使用示例
type ApiResponse = {
status: number;
data: any;
error: string | null;
dataTimestamp: number;
};
type DataProps = FilterKeys<ApiResponse, "data">;
// { data: any; dataTimestamp: number }
三、基于属性类型过滤
1、保留特定类型的属性
// 只保留函数类型的属性
type FunctionProperties<T> = {
[K in keyof T as T[K] extends Function ? K : never]: T[K];
};
// 使用示例
type MathLib = {
add: (a: number, b: number) => number;
version: string;
subtract: (a: number, b: number) => number;
};
type MathMethods = FunctionProperties<MathLib>;
// { add: (a: number, b: number) => number; subtract: (a: number, b: number) => number }
2、排除非特定类型的属性
// 排除函数类型的属性
type NonFunctionProperties<T> = {
[K in keyof T as T[K] extends Function ? never : K]: T[K];
};
// 使用示例
type MathProps = NonFunctionProperties<MathLib>;
// { version: string }
四、条件映射
// 将某些属性转为可选
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// 使用示例
type PartialUser = Optional<User, "age" | "name">;
// { id: number; name?: string; age?: number }
五、深度过滤
// 深度只读(递归)
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
// 深度可选(递归)
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
六、实用工具类型组合
// 创建严格类型,禁止额外属性
type Strict<T, U extends T> = T & {
[K in Exclude<keyof U, keyof T>]: never;
};
// 使用示例
function strictFunc<T>() {
return function <U extends Strict<T, U>>(value: U): U {
return value;
};
}
const createUser = strictFunc<{ name: string }>();
createUser({ name: "Alice" }); // OK
createUser({ name: "Bob", age: 30 }); // Error: 'age' not expected
这些技术可以组合使用,构建出非常灵活的类型系统,满足各种复杂的类型需求。
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于