Nhảy tới nội dung

Tạo type của tất cả phần tử từ array

Ở trang trước, đã giới thiệu cách tạo type của tất cả phần tử từ array.

ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
 
type Currency = (typeof currencies)[number];
type Currency = "CNY" | "EUR" | "GBP" | "JPY" | "KRW" | "USD"
ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
 
type Currency = (typeof currencies)[number];
type Currency = "CNY" | "EUR" | "GBP" | "JPY" | "KRW" | "USD"

Cách viết typeof currencies[number] có thể khó hiểu khi lần đầu nhìn thấy. Vì vậy sẽ giải thích chi tiết hơn.

Quan sát code ở trang trước

Về code tạo type của một phần tử từ array, tiếp tục từ trang trước, xác nhận lại với array tiền tệ.

ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
type Currency = (typeof currencies)[2];
type Currency = "GBP"
ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
type Currency = (typeof currencies)[2];
type Currency = "GBP"

Ở đây, 2 trong typeof currencies[2] được giải thích là literal type ở trang trước, nhưng có thực sự như vậy không? Hãy xác nhận bằng code sau.

ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
const index = 2 as const;
type Currency = (typeof currencies)[index];
'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?2749'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?
ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
const index = 2 as const;
type Currency = (typeof currencies)[index];
'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?2749'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?

Code trong đó 2 được hiểu là value đã bị lỗi.

Vậy hãy thử code mà rõ ràng là literal type.

ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
type Index = 2;
type Currency = (typeof currencies)[Index];
type Currency = "GBP"
ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
type Index = 2;
type Currency = (typeof currencies)[Index];
type Currency = "GBP"

Như vậy đã rõ ràng 2 trong typeof currencies[2] là literal type.

Literal type của số và number type

Mối quan hệ giữa literal type của 2number type có thể biểu diễn bằng tập hợp là 2number. Nói cách khác, number type hoạt động như một trong các literal type của số như 0, 1, 2...

Khi nói đến "một trong các type" thì đó là union type.

📄️ Union type

Union type trong TypeScript là cách biểu diễn "một trong các kiểu".

Hãy thử sử dụng union type của literal thay cho number type.

ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
type Currency = (typeof currencies)[0 | 1 | 2 | 3 | 4 | 5];
type Currency = "CNY" | "EUR" | "GBP" | "JPY" | "KRW" | "USD"
ts
const currencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] as const;
type Currency = (typeof currencies)[0 | 1 | 2 | 3 | 4 | 5];
type Currency = "CNY" | "EUR" | "GBP" | "JPY" | "KRW" | "USD"

Với type 0 | 1 | 2 | 3 | 4 | 5 cũng có thể tạo type của tất cả phần tử từ array currencies. Như vậy có thể thấy number type hoạt động như wildcard của literal type số.

Tổng quát hóa

Để kết thúc trang này, đây là code tổng quát hóa.

ts
type List = (string | number | boolean)[];
type Elem = List[number];
type Elem = string | number | boolean
ts
type List = (string | number | boolean)[];
type Elem = List[number];
type Elem = string | number | boolean

Từ type List, bằng cách viết List[number] đã tạo được string | number | boolean là type của tất cả phần tử.

Giới thiệu anti-pattern

Có thể tạo cùng type bằng index cụ thể như sau, nhưng hãy chú ý đây là anti-pattern.

ts
type List = (string | number | boolean)[];
type Elem = List[0]; // Cách viết nên tránh
type Elem = string | number | boolean
ts
type List = (string | number | boolean)[];
type Elem = List[0]; // Cách viết nên tránh
type Elem = string | number | boolean

Lý do cách viết này là anti-pattern là vì có thể gây nhầm lẫn type List là tuple type. List[0] tạo type từ phần tử cụ thể, nên có thể gây hiểu lầm rằng type của mỗi phần tử không giống nhau, nghĩa là List là tuple type chứ không phải array type. Vì array type coi type của tất cả phần tử là giống nhau, nên cách viết List[number] là phù hợp.