Skip to main content

[course] Making TypeScript Stick

keywords: typescript, frontendmasters

本篇非原創文章,內容整理自 Making TypeScript Stick @ Frontend Masters

Recent updates to TypeScript

Variadic Tuple Types

在 TypeScript 4 之前,雖然可以用 [number, ...T[]] 這種寫法:

// https://www.typescript-training.com/course/making-typescript-stick/03-recent-updates-to-typescript/
enum Sandwich {
Hamburger,
VeggieBurger,
GrilledCheese,
BLT,
}

// tuple
type SandwichOrder = [number, Sandwich, ...string[]];

const order1: SandwichOrder = [12.99, Sandwich.Hamburger, 'lettuce'];

// highlight-tart
// 在 TypeScript 4 之前,可以使用 ...T[] 這樣的寫法來讓 TS 推斷出 T 的型別,但是
function tail<T>(args: readonly [number, ...T[]]) {
const [_ignored, ...rest] = args;
return rest;
}

// 推斷出的結果是 (string | Sandwich)[],失去了原本 tuple 的型別資訊,應該要是 [Sandwich, ...string[]] 才對
const orderWithoutTotal = tail(order1);
// highlight-tart

但這種寫法會使得 TypeScript 無法正確反映出 Tuple 的型別。

在 TypeScript 4 之後,我們可以用 [number, ...T]下面這種寫法,讓它正確推斷出 tuple 的型別:

// 在 TypeScript 4 之後,可以使用 ...T 這樣的寫法來讓 TS 正確推斷出 tuple
function tail<T extends any[]>(args: readonly [number, ...T]) {
const [_ignored, ...rest] = args;
return rest;
}

// 如此,能正確推斷出 [Sandwich, ...string[]] 的 tuple
const orderWithoutTotal = tail(order1);

如此,就能夠正確推斷出 tuple 型別的內容。

更進一步來說,就是 TypeScript 的 tuple 也支援 spread operator 的使用

// Arr 會是 [number, string, boolean, boolean]
type Arr = [...[number, string], ...[boolean, boolean]];
const arr: Arr = [1, 'str', true, false];