跳至主要内容

[Day04] TS:如何把物件型別的所有屬性名稱取出變成 union type?試試看 keyof 吧!

前面兩天的文章中我們談到泛型(generics)的使用,以及如何透過 extends 來限制泛型可被帶入的型別。在後面的內容中,會越來越著重在如何透過 type 來產生另一個 type。

今天就來看看 keyof 的使用。

區分物件型別(type)和物件(value)

keyof 顧名思義就是把「物件型別(object type)」的 key 拿出來,但要留意的是,這裡提到的是「物件型別」,而不是真的「物件」,前者是 TypeScript 的型別,後者是 JavaScript 中的一個物件(object):

// Person 是一個 object type
type Person = {
firsName: string;
lastName: string;
};

// person 是 JavaScript 的 object (value)
const person = {
firstName: 'Aaron',
lastName: 'Chen',
};

如果不小心把真正的 object 當成 typescript 的 type 來使用的話,因為它不是型別的緣故,TypeScript 是會報錯的:

Typescript value and type

keyof operator 的使用

而這裡提到的 keyof 就只能用在「物件型別」上,使用方式非常簡單:

// Person 是一個 object type
type Person = {
firsName: string;
lastName: string;
};

type PersonKey = keyof Person;

滑鼠移到 PersonKey 上後將會看到:

typescript keyof

實際上的意思則是 "firsName" | "lastName"

typescript keyof

簡單來說,透過 keyof operator,就可以取出物件型別的 key,並建立成一個新的 type:

typescript keyof operator

搭配 & string 使用

由於「物件型別(object types)」的屬性名稱不一定是 string,也有可能是 numbersymbol,因此若有需要的話,可以搭配交集(&)的使用,也就是 & string

type PersonKey = keyof Person & string;

註:「物件型別」的 key 可以是 stringnumber,但 JavaScript 中「物件」的 key 只會是 stringsymbol

這時候 TS 就會明確知道說你要取出的是型別為 string 的 object key:

typescript keyof

小知識:any 的 keyof 是?

在 TypeScript 中,透過 keyof 則可以看到 any 的型別是 string | number | symbol

type KeyOfAny = keyof any; // type KeyOfAny = string | number | symbol

也就是說,在 TypeScript 中,能接受作為 key 的型別只能是 string、number 或 symbol,其他的型別像是 boolean 或 function 是不能被當作 key 的。

當我們試著把 object key 指定為 boolean 時,TS 會報錯:

TypeScript keyof

參考資料