之前我們講過了幾個 Utility 型別 Ⅰ,忘記了的小夥伴可以再來看看。TypeScript 還提供了其它的 Utility 型別工具:
Extract<T, U>
用於 從聯合類型中選取指定的成員
,返回一個新的聯合型別。
假設我們有一個聯合型別 TPhone,表示手機的類型,並且我們想要選取 Samsung 和 Sony 這兩種手機:
type TPhone = "Apple" | "Samsung" | "Mi" | "Sony";
type TExtractPhone = Extract<TPhone, "Samsung" | "Sony">;
const myPets: TExtractPhone[] = ["Samsung", "Sony"];
Extract 和 Pick 不同之處是:Extract 是從一個聯合類型中選取符合特定條件的成員,而 Pick 是從一個物件型別中選取指定的屬性。
Exclude<T, U>
用於 從聯合類型中排除指定的成員
,返回一個新的聯合類型。
假設我們有一個聯合型別 TPhone,表示手機的類型,並且我們想要排除 Mi 和 Sony 這兩種手機:
type TPhone = "Apple" | "Samsung" | "Mi" | "Sony";
type TExcludePhone = Exclude<TPhone, "Mi" | "Sony">;
const phone: TExcludePhone[] = ["Apple", "Samsung"];
Exclude 和 Omit 不同之處是:Extract 是從一個聯合類型中排除符合特定條件的成員,而 Omit 是從一個物件型別中排除指定的屬性。
Record<K, T>
的主要作用是將聯合類型當成每個 key,並且 value 為指定的型別,創建出一個新的型別。
interface IPhoneInfo {
model: string;
price: number;
}
type TPhones = "Apple" | "Samsung" | "Mi";
type TRecordPhones = Record<TPhones, IPhoneInfo>;
const recordPhones: TRecordPhones = {
Apple: { model: "iPhone 20 Pro", price: 55000 },
Samsung: { model: "Flip 10", price: 53000 },
Mi: { model: "xiaomi 20T Series", price: 45000 },
};
console.log(recordPhones.Apple); // 輸出: {model: "iPhone 20 Pro", price: 55000}
Required<T>
用於將型別 T 中的所有可選屬性變成必需屬性,返回一個新的型別。
interface IPerson {
name?: string;
age?: number;
}
type TRequiredPerson = Required<IPerson>;
const person: TRequiredPerson = {
name: "威爾豬",
age: 3,
};
Readonly<T>
用於將型別 T 中的所有屬性設為只讀,所以該型別 T 的屬性不能進行賦值操作。
interface IPerson {
name: string;
age: number;
}
type TReadOnlyPerson = Readonly<IPerson>;
const person: TReadOnlyPerson = {
name: "威爾豬",
age: 3,
};
person.name = "威爾羊"; // ❌ 錯誤:無法分配給 'name',因為它是只讀的。
ReturnType<T>
的主要作用是幫助我們確切地知道函式的返回值型別,以增加型別安全性。
const greet = (name: string): string => {
return `哈囉,${name}!`;
};
// 定義類型別名為 greet 函式返回值的型別
type TGreetReturnType = ReturnType<typeof greet>;
const result: TGreetReturnType = greet("威爾豬");
console.log(result); // 輸出: 哈囉,威爾豬!
在這個範例中,我們首先定義了一個 greet 函式,它接受一個參數並返回字串。接著,我們使用 typeof greet 來獲取 greet 函式的型別,然後使用 ReturnType<typeof greet>
來獲取該函數的返回值型別 string。
Awaited<T>
的主要作用是幫助我們在非同步函式中確切地知道 Promise 解析後的值的型別,從而增加型別安全性。
interface IData {
userId: number;
id: number;
title: string;
body: string;
}
const fetchData = async (): Promise<IData> => {
try {
const res = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await res.json();
return data;
} catch (error) {
console.error(error.message);
}
};
// 定義類型別名為非同步函式返回後的值的型別
type TPostData = Awaited<ReturnType<typeof fetchData>>;
const getPostInfo = async (): Promise<void> => {
const postData: TPostData = await fetchData();
console.log(postData.userId); // 輸出: 1
};
getPostInfo();
InstanceType<T>
的主要作用是幫助我們確切地知道類別實例的型別,以增加型別安全性。
class Person {
constructor(public name: string, public age: number) {}
}
type TInstancePerson = InstanceType<typeof Person>;
const person: TInstancePerson = new Person("威爾豬", 3);
在 Vue 官網 - Typing Component Template Refs 中也有使用到 InstanceType。
NonNullable<T>
用於將型別 T 中的所有 null 和 undefined 型別排除,返回一個新的型別。當我們想確保一個值不為 null 或 undefined 時,就可以使用。
type TNonNull = string | number | null | undefined;
type TNonNullable = NonNullable<TNonNull>;
Parameters<T>
用於從函數型別 T 中獲取函數的參數列表的型別。
type TAddFn = (a: number, b: number) => number;
type TAddParameters = Parameters<TAddFn>;
const add: TAddFn = (a, b) => a + b;
const params: TAddParameters = [2, 3];
const result = add(...params);
console.log(result); // 輸出: 5
ConstructorParameters<T>
用於從類別型別 T 中獲取建構函式的參數列表的型別。
class Person {
constructor(public name: string, public age: number) {}
}
type TConstructorParameters = ConstructorParameters<typeof Person>;
const params: TConstructorParameters = ["威爾豬", 3];
const person = new Person(...params);
console.log(person); // 輸出: Person {name: '威爾豬', age: 3}
ThisParameterType<T>
的主要作用是幫助我們確定方法中 this 對象的型別。
function handleToString(this: number): string {
return this.toString();
}
const numberToString = (
num: ThisParameterType<typeof handleToString>
): string => {
return handleToString.call(num);
};
const result = numberToString(3);
console.log(typeof result); // 輸出: string
這些內建的 Utility 型別工具可以讓我們更輕鬆地選取、排除和轉換型別,並提高了程式碼的可讀性、減少錯誤並提高型別安全性,威爾豬這邊只列出一部分,官網 還有其它的 Utility 型別可以看看。
至於更進階的 Utility 型別通常是根據特定需求使用 TypeScript 內置的型別組合而成的較複雜型別,用於解決更複雜的型別問題,通常需要更多的型別知識和技能。不過威爾豬常用的還是 Partial、Pick、Omit、Extract、Exclude、InstanceType 等這些基本型別工具,其它的就看小夥伴們在專案中有沒有需要使用到。