iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0

之前我們講過了幾個 Utility 型別 Ⅰ,忘記了的小夥伴可以再來看看。TypeScript 還提供了其它的 Utility 型別工具:

Extract

Extract<T, U> 用於 從聯合類型中選取指定的成員,返回一個新的聯合型別。

假設我們有一個聯合型別 TPhone,表示手機的類型,並且我們想要選取 Samsung 和 Sony 這兩種手機:

type TPhone = "Apple" | "Samsung" | "Mi" | "Sony";
type TExtractPhone = Extract<TPhone, "Samsung" | "Sony">;

const myPets: TExtractPhone[] = ["Samsung", "Sony"];

https://ithelp.ithome.com.tw/upload/images/20230927/20141250r1qZqvOhRg.png

Extract 和 Pick 不同之處是:Extract 是從一個聯合類型中選取符合特定條件的成員,而 Pick 是從一個物件型別中選取指定的屬性。

Exclude

Exclude<T, U> 用於 從聯合類型中排除指定的成員,返回一個新的聯合類型。

假設我們有一個聯合型別 TPhone,表示手機的類型,並且我們想要排除 Mi 和 Sony 這兩種手機:

type TPhone = "Apple" | "Samsung" | "Mi" | "Sony";
type TExcludePhone = Exclude<TPhone, "Mi" | "Sony">;

const phone: TExcludePhone[] = ["Apple", "Samsung"];

https://ithelp.ithome.com.tw/upload/images/20230927/20141250l8fZFRQ3pe.png

Exclude 和 Omit 不同之處是:Extract 是從一個聯合類型中排除符合特定條件的成員,而 Omit 是從一個物件型別中排除指定的屬性。

Record

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

Required<T> 用於將型別 T 中的所有可選屬性變成必需屬性,返回一個新的型別。

interface IPerson {
  name?: string;
  age?: number;
}

type TRequiredPerson = Required<IPerson>;

const person: TRequiredPerson = {
  name: "威爾豬",
  age: 3,
};

https://ithelp.ithome.com.tw/upload/images/20230927/20141250UrbCSJH1yP.png

Readonly

Readonly<T> 用於將型別 T 中的所有屬性設為只讀,所以該型別 T 的屬性不能進行賦值操作。

interface IPerson {
  name: string;
  age: number;
}

type TReadOnlyPerson = Readonly<IPerson>;

const person: TReadOnlyPerson = {
  name: "威爾豬",
  age: 3,
};

person.name = "威爾羊"; // ❌ 錯誤:無法分配給 'name',因為它是只讀的。

https://ithelp.ithome.com.tw/upload/images/20230927/20141250cr2xkIFH2Z.png

ReturnType

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

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

InstanceType<T> 的主要作用是幫助我們確切地知道類別實例的型別,以增加型別安全性。

class Person {
  constructor(public name: string, public age: number) {}
}

type TInstancePerson = InstanceType<typeof Person>;

const person: TInstancePerson = new Person("威爾豬", 3);

https://ithelp.ithome.com.tw/upload/images/20230927/201412505kKcdOYjIp.png

Vue 官網 - Typing Component Template Refs 中也有使用到 InstanceType。

NonNullable

NonNullable<T> 用於將型別 T 中的所有 null 和 undefined 型別排除,返回一個新的型別。當我們想確保一個值不為 null 或 undefined 時,就可以使用。

type TNonNull = string | number | null | undefined;
type TNonNullable = NonNullable<TNonNull>;

https://ithelp.ithome.com.tw/upload/images/20230927/20141250pNqTY9CwDg.png

Parameters

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

https://ithelp.ithome.com.tw/upload/images/20230927/20141250N1hcbrgRl0.png

ConstructorParameters

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

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

https://ithelp.ithome.com.tw/upload/images/20230927/20141250PcLLLuulxU.png


這些內建的 Utility 型別工具可以讓我們更輕鬆地選取、排除和轉換型別,並提高了程式碼的可讀性、減少錯誤並提高型別安全性,威爾豬這邊只列出一部分,官網 還有其它的 Utility 型別可以看看。

至於更進階的 Utility 型別通常是根據特定需求使用 TypeScript 內置的型別組合而成的較複雜型別,用於解決更複雜的型別問題,通常需要更多的型別知識和技能。不過威爾豬常用的還是 Partial、Pick、Omit、Extract、Exclude、InstanceType 等這些基本型別工具,其它的就看小夥伴們在專案中有沒有需要使用到。


上一篇
高級型別
下一篇
裝飾器 ( Decorators )
系列文
用不到 30 天學會基本 TypeScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言