- Description : There is currently no Chinese translation of the latest official documents of TypeScript on the Internet, so there is such a translation plan. Because I am also a beginner in TypeScript, I cannot guarantee that the translation will be 100% accurate. If there are errors, please point out in the comment section;
- translation content : The tentative translation content is TypeScript Handbook , and other parts of the translation document will be added later;
- project address : TypeScript-Doc-Zh , if it helps you, you can click a star~
The official document address of this chapter: Mapped Types
Mapping type
Sometimes we don't want to rewrite the code, at this time we need to create another type based on one type.
Index signatures are used to declare types for attributes that have not been declared in advance, while mapping types are constructed based on the syntax of index signatures.
type OnlyBoolsAndHorses = {
[key: string]: boolean | Horse;
};
const conforms: OnlyBoolsAndHorses = {
del: true,
rodney: false,
};
The mapping type is also a generic type. It uses PropertyKey
(attribute key) (usually keyof ) to traverse all the keys to create a new type:
type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};
In this example, OptionsFlags
will accept Type
and change their values to boolean values.
type FeatureFlags = {
darkMode: () => void;
newUserProfile: () => void;
};
type FeatureOptions = OptionsFlags<FeatureFlags>;
^
/*
type FeatureOptions = {
darkMode: boolean;
newUserProfile: boolean;
}
*/
Mapping modifier
There are two additional modifiers available when mapping, namely readonly
and ?
, which are used to declare the read-only and optional properties of the attribute respectively.
To remove or add modifiers, just add the prefix -
or +
to the modifier. If no prefix is added, +
will be used by default.
// 移除类型中属性的只读性
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;
}
*/
Implement key remapping through as
In TypeScript4.1 or higher, you can use the as
clause in the mapping type to implement key remapping:
type MappedTypeWithNewProperties<Type> = {
[Properties in keyof Type as NewKeyType]: Type[Properties]
}
You can use such as the 161b1be92a7062 template literal type to create new attribute names from the original attribute names:
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;
}
*/
You can generate never
type by condition type to filter out certain keys:
// 移除 kind 属性
type Exclude<T,U> = T extends U ? never : T
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;
}
*/
Not only string | number | symbol
, but any union type can be mapped:
type EventConfig<Events extends { kind: string }> = {
[E in Events as E['kind']]: (event: E) => void;
}
type SqureEvent = { kind: 'squre', x: number, y: number };
type CircleEvent = { kind: 'circle', radius: number };
type Config = EventConfig<SqureEvent | CricleEvent>
/**
type Config = {
squre: (event: SqureEvent) => void;
circle: (event: CircleEvent) => void;
}
/
Further application of mapping types
The mapping type can also be used in conjunction with other features introduced in this chapter (type manipulation). For example, following is a use condition type mapping type , whether a literal is set according to the object true
properties pii
, it will return true
or false
:
type ExtractPII<Type> = {
[Property in keyof Type]: Type[Property] extends { pii: true } ? true : false
};
type DBFileds = {
id: { format: 'incrementing' };
name: { type: string; pii: true };
};
type ObjectsNeedingGDPRDeletion = ExtractPII<DBFileds>;
^
/*
type ObjectsNeedingGDPRDeletion = {
id: false;
name: true;
}
*/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。