對應類型

當您不希望重複時,有時一個類型需要建立在另一個類型之上。

對映類型建立在索引簽章的語法上,用於宣告尚未預先宣告的屬性類型

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

進一步探索

映射類型適用於此類型操作區段中的其他功能,例如這裡是 使用條件類型的映射類型,它會傳回 truefalse,視物件是否將屬性 pii 設定為文字 true

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 文件是一個開放原始碼專案。協助我們改善這些頁面 傳送 Pull Request

此頁面的貢獻者
OTOrta Therox (7)
SFSergey Falinsky (2)
LLuke (1)
Wwebstrand (1)
SGHSteven G. Harms (1)
5+

最後更新:2024 年 3 月 21 日