一起聊聊 TypeScript 中的實(shí)用類(lèi)型(utility type)和轉(zhuǎn)換類(lèi)型
在學(xué)習(xí) TypeScript 中遇到了Record 這個(gè)類(lèi)型, 一開(kāi)始不知道其用途, 查找了一下說(shuō)明才得知:
Record<K extends keyof any, T> 是 TypeScript 提供的一個(gè)實(shí)用類(lèi)型(utility type),用于構(gòu)造一個(gè)對(duì)象類(lèi)型,其中鍵 K 的集合可以是任意類(lèi)型(通常是字符串、數(shù)字或符號(hào)),對(duì)應(yīng)的值類(lèi)型為 T。
1. 詳細(xì)解釋
1.1 定義
Record<K extends keyof any, T> 的定義如下:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
- K extends keyof any:表示 K 可以是任何合法的鍵類(lèi)型。keyof any 是 TypeScript 中的一個(gè)特殊類(lèi)型,它等價(jià)于 string | number | symbol。
- T:表示屬性的值的類(lèi)型。
- { [P in K]: T; }:這是一種映射類(lèi)型語(yǔ)法,表示生成一個(gè)對(duì)象類(lèi)型,這個(gè)對(duì)象的鍵是 K 中的每一個(gè)鍵,其對(duì)應(yīng)的值類(lèi)型都是 T。
1.2 用法示例
- 創(chuàng)建一個(gè)簡(jiǎn)單的對(duì)象類(lèi)型: 假設(shè)我們想要?jiǎng)?chuàng)建一個(gè)對(duì)象類(lèi)型,鍵是字符串,值是數(shù)字:
type StringToNumberMap = Record<string, number>;
const example: StringToNumberMap = {
a: 1,
b: 2,
c: 3
};
- 限制鍵的集合: 假設(shè)我們有一組特定的鍵,值的類(lèi)型是布爾型:
type Options = "option1" | "option2" | "option3";
type OptionFlags = Record<Options, boolean>;
const example: OptionFlags = {
option1: true,
option2: false,
option3: true
};
- 結(jié)合接口使用: 如果我們有一個(gè)接口Person,我們想要?jiǎng)?chuàng)建一個(gè)包含多個(gè)Person對(duì)象的記錄:
interface Person {
name: string;
age: number;
}
type PersonDictionary = Record<string, Person>;
const persons: PersonDictionary = {
john: { name: "John Doe", age: 25 },
jane: { name: "Jane Smith", age: 30 }
};
1.3 詳細(xì)示例
假設(shè)我們需要管理一組用戶,每個(gè)用戶都有一個(gè)唯一的標(biāo)識(shí)符(ID)。我們可以使用 Record 來(lái)定義一個(gè)用戶字典:
interface User {
id: number;
name: string;
email: string;
}
type UserDictionary = Record<number, User>;
const users: UserDictionary = {
1: { id: 1, name: "John Doe", email: "john.doe@example.com" },
2: { id: 2, name: "Jane Smith", email: "jane.smith@example.com" },
3: { id: 3, name: "Emily Johnson", email: "emily.johnson@example.com" }
};
// 訪問(wèn)用戶信息
console.log(users[1].name); // 輸出: John Doe
在這個(gè)示例中:
- User 接口定義了用戶對(duì)象的結(jié)構(gòu)。
- UserDictionary 使用 Record<number, User> 創(chuàng)建了一個(gè)類(lèi)型,該類(lèi)型的鍵是數(shù)字,值是 User 類(lèi)型。
- users 變量是一個(gè) UserDictionary 類(lèi)型的對(duì)象,包含多個(gè)用戶條目。
2. 類(lèi)型工具
Record<K extends keyof any, T> 類(lèi)型在 TypeScript 中非常有用,可以用來(lái)定義一個(gè)鍵和值類(lèi)型的映射。它允許我們動(dòng)態(tài)地創(chuàng)建具有特定鍵集合和值類(lèi)型的對(duì)象類(lèi)型,廣泛應(yīng)用于需要鍵值對(duì)數(shù)據(jù)結(jié)構(gòu)的場(chǎng)景。
在 TypeScript 中還有不少類(lèi)似的類(lèi)型工具用于操作和轉(zhuǎn)換類(lèi)型。以下是它們的具體區(qū)別和用途:
- Partial
作用:將類(lèi)型 T 的所有屬性變?yōu)榭蛇x。
用法:
interface Person {
name: string;
age: number;
}
type PartialPerson = Partial<Person>;
// Equivalent to: { name?: string; age?: number; }
- Required
作用:將類(lèi)型 T 的所有屬性變?yōu)楸匦琛?/p>
用法:
interface Person {
name?: string;
age?: number;
}
type RequiredPerson = Required<Person>;
// Equivalent to: { name: string; age: number; }
- Readonly
作用:將類(lèi)型 T 的所有屬性變?yōu)橹蛔x。
用法:
interface Person {
name: string;
age: number;
}
type ReadonlyPerson = Readonly<Person>;
// Equivalent to: { readonly name: string; readonly age: number; }
- Pick<T, K extends keyof T>
作用:從類(lèi)型 T 中挑選一組屬性 K 組成新的類(lèi)型。
用法:
interface Person {
name: string;
age: number;
address: string;
}
type PersonNameAndAge = Pick<Person, 'name' | 'age'>;
// Equivalent to: { name: string; age: number; }
- Record<K extends keyof any, T>
作用:構(gòu)建一個(gè)類(lèi)型,其鍵為 K 類(lèi)型,值為 T 類(lèi)型。
用法:
type PersonRecord = Record<string, number>;
// Equivalent to: { [key: string]: number; }
- Exclude<T, U>
作用:從類(lèi)型 T 中排除可以賦值給 U 的類(lèi)型。
用法:
type T = string | number | boolean;
type Excluded = Exclude<T, boolean>;
// Equivalent to: string | number
- Extract<T, U>
作用:從類(lèi)型 T 中提取可以賦值給 U 的類(lèi)型。
用法:
type T = string | number | boolean;
type Extracted = Extract<T, boolean>;
// Equivalent to: boolean
- Omit<T, K extends keyof any>
作用:構(gòu)建一個(gè)類(lèi)型,其具有類(lèi)型 T 的屬性,除了那些在 K 中的屬性。
用法:
interface Person {
name: string;
age: number;
address: string;
}
type PersonWithoutAddress = Omit<Person, 'address'>;
// Equivalent to: { name: string; age: number; }
- NonNullable
作用:從類(lèi)型 T 中排除 null 和 undefined。
用法:
type T = string | number | null | undefined;
type NonNullableT = NonNullable<T>;
// Equivalent to: string | number
- Parameters<T extends (...args: any) => any>
作用:獲取函數(shù)類(lèi)型 T 的參數(shù)類(lèi)型組成的元組。
用法:
type Func = (a: string, b: number) => void;
type Params = Parameters<Func>;
// Equivalent to: [string, number]
這些類(lèi)型工具在類(lèi)型操作和變換中非常有用,幫助開(kāi)發(fā)者更靈活地處理和定義類(lèi)型。