映射类型

当您不想重复自己时,有时类型需要基于另一种类型。

映射类型基于索引签名的语法,用于声明尚未提前声明的属性的类型。

ts
type OnlyBoolsAndHorses = {
[key: string]: boolean | Horse;
};
 
const conforms: OnlyBoolsAndHorses = {
del: true,
rodney: false,
};
Try

映射类型是一种泛型类型,它使用 PropertyKey 的并集(通常通过 keyof 创建)来迭代键以创建类型。

ts
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
Try

在此示例中,OptionsFlags 将获取类型 Type 中的所有属性,并将它们的值更改为布尔值。

ts
type Features = {
darkMode: () => void;
newUserProfile: () => void;
};
 
type FeatureOptions = OptionsFlags<Features>;
type FeatureOptions = { darkMode: boolean; newUserProfile: boolean; }
Try

映射修饰符

在映射过程中,可以应用两个额外的修饰符:readonly?,它们分别影响可变性和可选性。

可以通过在前面添加 -+ 来删除或添加这些修饰符。如果不添加前缀,则假定为 +

ts
// Removes 'readonly' attributes from a type's properties
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; }
Try
ts
// Removes 'optional' attributes from a type's properties
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; }
Try

通过 as 重映射键

在 TypeScript 4.1 及更高版本中,可以使用映射类型中的 as 子句重新映射映射类型中的键。

ts
type MappedTypeWithNewProperties<Type> = {
[Properties in keyof Type as NewKeyType]: Type[Properties]
}

您可以利用 模板字面量类型 等功能从之前的属性名创建新的属性名。

ts
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; }
Try

您可以通过生成 never 来过滤掉键,方法是在条件类型中使用条件类型。

ts
// Remove the 'kind' property
type RemoveKindField<Type> = {
[Property in keyof Type as Exclude<Property, "kind">]: Type[Property]
};
 
interface Circle {
kind: "circle";
radius: number;
}
 
type KindlessCircle = RemoveKindField<Circle>;
type KindlessCircle = { radius: number; }
Try

您可以遍历任意联合类型,不仅是 string | number | symbol 的联合类型,还可以遍历任何类型的联合类型。

ts
type EventConfig<Events extends { kind: string }> = {
[E in Events as E["kind"]]: (event: E) => void;
}
 
type SquareEvent = { kind: "square", x: number, y: number };
type CircleEvent = { kind: "circle", radius: number };
 
type Config = EventConfig<SquareEvent | CircleEvent>
type Config = { square: (event: SquareEvent) => void; circle: (event: CircleEvent) => void; }
Try

进一步探索

映射类型与本节中其他类型操作功能配合使用效果很好,例如,这里有一个 使用条件类型的映射类型,它根据对象是否具有设置为文字 true 的属性 pii 返回 truefalse

ts
type ExtractPII<Type> = {
[Property in keyof Type]: Type[Property] extends { pii: true } ? true : false;
};
 
type DBFields = {
id: { format: "incrementing" };
name: { type: string; pii: true };
};
 
type ObjectsNeedingGDPRDeletion = ExtractPII<DBFields>;
type ObjectsNeedingGDPRDeletion = { id: false; name: true; }
Try

TypeScript 文档是一个开源项目。帮助我们改进这些页面 通过发送拉取请求

贡献者
OTOrta Therox (7)
SFSergey Falinsky (2)
LLuke (1)
Wwebstrand (1)
SGHSteven G. Harms (1)
5+

最后更新时间:2024 年 3 月 21 日