当你不想重复自己时,有时一个类型需要以另一个类型为基础。
自定义 Mapped Types
type OnlyBoolsAndHorses = {
[key: string]: boolean | Horse;
};
const conforms: OnlyBoolsAndHorses = {
del: true,
rodney: false,
};
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
type FeatureFlags = {
darkMode: () => void;
newUserProfile: () => void;
};
type FeatureOptions = OptionsFlags<FeatureFlags>;
// 相当于
type FeatureOptions = { darkMode: boolean; newUserProfile: boolean; }
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property];
};
type LockedAccount = {
readonly id: string;
readonly name: string;
};
type UnlockedAccount = CreateMutable<LockedAccount>;
// 相当于
type UnlockedAccount = { id: string; name: string; }
type Concrete<Type> = {
[Property in keyof Type]-?: Type[Property];
};
type MaybeUser = {
id: string;
name?: string;
age?: number;
};
type User = Concrete<MaybeUser>;
// 相当于
type User = { id: string; name: string; age: number; }
Key Remapping via as
type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};
interface Person {
name: string;
age: number;
location: string;
}
type LazyPerson = Getters<Person>;
// 相当于
type LazyPerson = { getName: () => string; getAge: () => number; getLocation: () => string; }
系统内置 Mapped Types
Partial
使 T 中所有的属性都变为可选
type Partial<T> = {
[P in keyof T]?: T[P];
};
Required
使 T 中所有的属性都变为必选
type Required<T> = {
[P in keyof T]-?: T[P];
};
Readonly
使 T 中的所有属性都变成只读属性
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Pick
从 T 中挑选 key 为 K 的组成一个新的类型
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Record
使用 K 做为 key,生成类型为 T 的类型
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Exclude
T 和 U 的差集
type Exclude<T, U> = T extends U ? never : T;
Extract
T 和 U 的交集
type Extract<T, U> = T extends U ? T : never;
Omit
从 T 中排除若干个 key,生成一个新类型
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
NonNullable
排除了 null 和 undefined
type NonNullable<T> = T & {};
ReturnType
获取函数返回值的类型
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;