映射类型与键重映射
00:00
TypeScript映射类型与键重映射详解:Mapped Types、as子句与高级模式。
1. 映射类型基础
1.1 基本语法
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
type Optional<T> = {
[K in keyof T]?: T[K];
};
interface User {
name: string;
age: number;
}
type ReadonlyUser = Readonly<User>;
// { readonly name: string; readonly age: number }
1.2 映射类型与索引签名
// 从联合类型创建对象类型
type Flags = { [K in 'read' | 'write' | 'execute']: boolean };
// { read: boolean; write: boolean; execute: boolean }
2. 键重映射(Key Remapping)
2.1 as 子句
TypeScript 4.1 引入 as 子句,允许在映射时转换键名:
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface User {
name: string;
age: number;
}
type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number }
2.2 过滤键
type RemoveNull<T> = {
[K in keyof T as T[K] extends null | undefined ? never : K]: T[K];
};
type User = { name: string; age: null; email: string | undefined };
type CleanUser = RemoveNull<User>;
// { name: string; email: string | undefined }
2.3 键名转换
// 添加前缀
type Prefix<T, P extends string> = {
[K in keyof T as `${P}${Capitalize<string & K>}`]: T[K];
};
type PrefixedUser = Prefix<User, 'user'>;
// { userName: string; userAge: number }
3. 内置映射类型
| 类型 | 说明 |
|---|---|
Partial<T> | 所有属性可选 |
Required<T> | 所有属性必需 |
Readonly<T> | 所有属性只读 |
Pick<T, K> | 选取部分属性 |
Omit<T, K> | 排除部分属性 |
Record<K, V> | 构建键值对类型 |
Exclude<U, E> | 从联合类型排除 |
Extract<U, E> | 从联合类型提取 |
NonNullable<T> | 排除 null/undefined |
4. 高级映射模式
4.1 深层 Partial
type DeepPartial<T> = T extends Function
? T
: T extends object
? { [K in keyof T]?: DeepPartial<T[K]> }
: T;
4.2 值类型映射
type MapValues<T, F extends (v: any) => any> = {
[K in keyof T]: F extends (v: T[K]) => infer R ? R : never;
};
4.3 条件映射
type ConditionalPick<T, Condition> = {
[K in keyof T as T[K] extends Condition ? K : never]: T[K];
};
type StringProps = ConditionalPick<User, string>; // { name: string }