這是 TS 系列的最後一篇文章,今天我們會來討論 Typescript narrowing 跟 type guard!
function example(input: string | boolean) {
console.log(input.length); // 這裡會報錯,Property 'length' does not exist on type 'string | boolean'.
}
我們先來看看上面的程式碼,在input.length
的地方會報錯,原因是因為我們的 input 有可能會是 string 或是 boolean,但是length
的方法只有 string 有,boolean 沒有這個方法,所以就報錯了!如果讀者有看過我們前一篇的 generics 文章的話,應該記得我們也有遇到類似的問題,那時候我們的解決方法是用extends
來給予 generics 更嚴格的 type,而在這裡我們可以用一個叫做 type guard 的程式碼來解決這個問題。我們看下面的程式碼:
function example(input: string | boolean) {
if (typeof input === "string") {
console.log(input.length);
}
}
我們用一個 if 條件句讓 if 條件句裡面的程式碼只有 input 是 string 的情況下才會被執行到。這段typeof input === "string"
條件我們就稱它為 type guard,而透過方法,像是 type guard,來把 type 限制成更小範圍的 type 的行為我們就稱它為 narrowing。了解這兩個的意思之後,我們來看幾個 TS 的 narrowing 方法。
typeof
type guard對 JS 熟悉的朋友應該對 typeof 不會陌生,typeof 可以分辯出以下幾種 type:
"string";
"number";
"bigint";
"boolean";
"symbol";
"undefined";
"object";
"function";
我們只要把typeof
type guard 放在 if 條件句中,就可以做到 narrowing 摟!
我們回來看看剛剛的這個 function,這時候我們如果把箭頭移動到 input 上,typescript 會如何判定 input 的 type 呢?讀者可以猜猜看!
function example(input: string | boolean) {
if (typeof input === "string") {
return ...
}
console.log(input)
}
答案是 Typescript 會判定 input 為 boolean!因為 input 為 string 的情況已經在剛剛的 type guard 中 return 了,而這個透過各個程式碼的能不能被觸及到的 Typescript 功能就叫做----Control flow analysis。因為這個重要的功能,我們可以用它來處理現實中其他更為複雜的情況!
另外一種更為"暴力"的 narrowing 方式,叫做 type predicates,就是主動的去給變數 type,我們一樣舉上面的例子,在這裡我們不用到 type guard,我們只要用 keywordas
來斷言 input 是什麼 type,它就會是什麼 type,像是下面的例子,雖然我們的input有可能是string或是boolean,但是因為我們斷言他是string,所以在使用length的時候就不會報錯摟!
function example(input: string | boolean) {
console.log((input as string).length);
}
今天大概的介紹了 narrowing 和 type guard!TS 系列只有短短的四篇的篇幅,完全無法去討論全部 TS 的功能,其他就等待讀者去自己閱讀拉!
面試題:
有打錯或是問題,非常歡迎在下面留言討論!
也可以追蹤我的medium,裡面不定期會寫一些最近在研究的東西或是想法!