在 TypeScript 中,映射类型 (Mapped Types) 允许我们基于已有类型创建新的类型,通常用于转换属性的类型、修改可选性或只读性等。结合映射类型,我们可以创建更灵活的类型定义,适用于不同的场景。
映射类型的基本语法
映射类型的核心语法如下:
type MappedType<T> = {
[K in keyof T]: NewType;
};
其中:
keyof T 获取 T 的所有属性键名。
K in keyof T 遍历 T 的所有键。
NewType 是新的属性类型。
结合映射类型创建新的类型
- 修改属性类型
我们可以使用映射类型将对象的所有属性转换为不同的类型:
type ConvertToBoolean<T> = {
[K in keyof T]: boolean;
};
type User = {
name: string;
age: number;
};
type BooleanUser = ConvertToBoolean<User>;
// 结果: { name: boolean; age: boolean; }
这里 ConvertToBoolean<User> 将 User 类型的所有属性转换为 boolean 类型。
- 设为可选属性
使用 ? 让所有属性变为可选:
type Optional<T> = {
[K in keyof T]?: T[K];
};
type PartialUser = Optional<User>;
// 结果: { name?: string; age?: number; }
- 设为只读属性
使用 readonly 让所有属性变为只读:
type ReadonlyType<T> = {
readonly [K in keyof T]: T[K];
};
type ReadonlyUser = ReadonlyType<User>;
// 结果: { readonly name: string; readonly age: number; }
- 结合条件类型
我们可以结合条件类型来过滤某些属性:
type RemoveStringProps<T> = {
[K in keyof T as T[K] extends string ? never : K]: T[K];
};
type FilteredUser = RemoveStringProps<User>;
// 结果: { age: number; } (去除了 name)
这里 as T[K] extends string ? never : K 过滤掉 string 类型的属性。
应用场景
数据转换:将 API 返回的数据转换为符合业务逻辑的类型。
类型安全:确保对象的属性符合预期类型。
动态类型生成:根据已有类型自动生成新的类型,减少重复代码
interface Points {
开始写作: {
查看: 1_001_001
}
首页: {
查看: 1_002_001
}
}
// 提取所有的值作为请求参数
type DeepValueOf<T> = T extends object
? { [K in keyof T]: DeepValueOf<T[K]> }[keyof T]
: T
type RequestParams = DeepValueOf<Points>