calendar_todayJuly 14, 2018
TypeScript 3.0 RC 版本發布,新增了 unknown
型別。unknown
顧名思義就是不知道這個型別是什麼型別的型別(好繞口令)。 看似和現有的 any
型別一樣,但卻又不盡相同。
在了解 unknown
型別前先來回顧現有的 any
型別。any 型別可以是任何型別,任何變數只要宣告成 any
型別,就會失去 TypeScript 型別檢查機制,使開發時期倒退到傳統 JavaScript 的動態型別。
上面將 foo
宣告成 any
,但實際上是數值型別。除了第一行可以正常執行,接下來幾行的程式碼在執行時期(runtime)會出錯。開發時期由於是 any
型別,TypeScript 認為它可以是任何型別,因此是可以正常編譯的。為了要解決 any
型別太過寬鬆,導致開發時期不容易偵錯,因此誕生了 unknown
型別。
unknown
型別可以想像成只能 set-only
的 any
型別。依樣可以指派任何型別的值給 unknown
,但要對 unknown
型別操作時,必須轉成 unknown
以外的型別,否則便會出錯。此外, unknown
只能指派給同樣是 unknown
型別或是 any
型別,不像 any
型別可以指派給 string
、number
等任何型別。
const foo: unknown = 10;
const bar: any = foo;
const bar2: unknown = foo;
// 下面*開發時期*每一行都會跳警告
const bar3: number = foo; // unknown 只能指派給 unknown
const bar4: string = foo; // unknown 只能指派給 unknown
foo.x.prop; // unknown 不能直接操作屬性、方法、建構式
foo.y.prop;
foo.z.prop;
foo();
new foo();
upperCase(foo);
foo`hello world!`;
function upperCase(x: string) {
return x.toUpperCase();
}
foo.toFixed(1); // error! 即使目前實際型別是數字,仍不能直接對 unknown 操作
if (typeof foo === 'number') {
foo.toFixed(1); // ok. TypeScript 推斷是 number 型別
}
if (typeof foo === 'string') {
foo.toUpperCase(); // ok. TypeScript 推斷是 string 型別
}
const foo2 = foo as string; // 強制轉型
foo2.toUpperCase(); // ok. 因為 foo2 現在被轉型成 string 型別
大部分情況下,unknown
型別幾乎可以取代現有的 any
型別,確保當下能斷定目前變數到底是什麼型別在對其進行操作,降低 any
型別帶來的不確定性。
Written by Jasper Jian who lives and works in Taiwan building useful things. You should follow him on Twitter