iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0

今天要講的東西,讓我超頭痛的,因為TypeScript當中的很多運算符,字面上看起來是一個意思,但實際運作起來又是別的意思,我們今天來看一些運算符跟實際例子吧。

今天準備不足,所以內文大多是官網的範例,再加上自己的詮釋。

keyof

看到key就會覺得是要講物件當中,key-value pair的key,這邊的確是這個意思,這個運算符會提取物件當中那個"key的型別":

interface Person {
  name: string;
  age: number;
}
// `keyof Person` 會創造出一個Union type: "name" | "age" 這兩個字串
function printPersonProperty(person: Person, property: keyof Person) {
  console.log(`${property}: "${person[property]}"`);
}
let person = {
  name: "Max",
  age: 27
};
printPersonProperty(person, "name"); // name: "Max"
//上面這行第二個參數只能放"name"或者"age"唷,不是任何字串或數字

這樣子的用法我一時不知道要用在哪邊,但後來想想,用在JavaScriptMap物件上非常好用,畢竟Map物件key的型別可以不侷限於字串或數字,所以透過keyof取用一個Map物件的key,藉此限縮型別,是個不錯的做法。

typeof

JavaScript其實已經有typeof這個運算符了,而TypeScript也有一個,但他只能在後面接上一個變數,而不能是一個"值":

let s = "hello";
let n: typeof s;
//typeof後面只能接s"變數",而不能是"值"

乍看之下其實用途不算太大,畢竟我們通常翻得到s是什麼型別,但作為組合技使用,效果就不錯。

function f() {
  return { x: 10, y: 3 };
}
type P = ReturnType<typeof f>;
//所以type P就會是{x: number, y: number}

indexed access type

這個用法可以物件裡面當中,其特地"值"的型別給取出來,有別於上面keyof取的是key的型別,是個有趣的對比:

type Person = { age: number; name: string; alive: boolean };
type Age = Person["age"];
// Age就會代表型別number

在上面例子Person[]的中括號中,我們甚至可以在裡面進行其他運算,達成更複雜的效果:

type Person = { age: number; name: string; alive: boolean };

type I1 = Person["age" | "name"];
//這行我們去取Person物件中,key age"或"key name的型別
//也就是number | string
 
type I2 = Person[keyof Person];
//這行我們先對Person進行keyof運算,所以得到的結果就是:
// number | string | boolean
 
type AliveOrName = "alive" | "name";
//我們當然也能用個聯合型別,放進下面中括號內進行運算
type I3 = Person[AliveOrName];
//於是I3指涉的型別就是
//boolean | string

//如果特地想要取用Person當中錯誤的key
type I4 = Person["ali"]
//TypeScript會特地報錯
//Property 'ali' does not exist on type 'Person'.

同樣的,除了物件,我們也能用在陣列上:

const MyArray = [
  { name: "Alice", age: 15 },
  { name: "Bob", age: 23 },
  { name: "Eve", age: 38 },
];
 
type Person = typeof MyArray[number];
//中括號這邊代表的是數字型別,所以可能是0,1,2,3,4...
//而MyArray[number]只會代表{name: string, age: number}
我們還能再更進一步取用陣列當中的物件當中的值的型別(超饒口吧!)
type Age = typeof MyArray[number]["age"]

講到這邊其實有點昏頭了,像上面中括號內的運算,我們既能像一般物件那樣,去取用特定的key,如["name"],卻也能放型別[number],但這邊卻不是要拿出number這個key所代表的value的型別(真的很饒口...)。所以我目前對這些概念只覺得:大概理解就好0rz,真的要用時再來查也不遲。


上一篇
第19天!函式多載(function overloads)
下一篇
第21天!TypeScript與React!
系列文
你也對開始使用typescript感到無力嗎?我也是 - 30天初探typescript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言