TypeScript 筆記:unknown 簡介


Posted by SimonAllen on 2021-08-11

延續上一篇 TS 筆記末尾,若版本允許,使用 unknown 會比 any 更好一點,此篇就來簡介一下 unknown:

unknown

unknown 型別容易與 any 搞混,其在 TypeScript 3.0 版提出,也是所有型別的聯集。unknown 意指未知型別,表示不知道當下是何種型別。使用 unknown 會允許 TypeScript 在之後仍可以賦值為任意型別。

unknown 和 any 的差異:

  • 不能直接操作屬性、方法、建構式
  • 無法重新賦值給 unknown 或 any 外的型別
  • 需要斷言或限縮型別

不能直接操作屬性、方法、建構式

在使用 any 的情境下,我們可以這樣寫,即便數值 1 根本沒有 somethingMethod 這個方法,TypeScript 仍不會報錯可以正常編譯。

let anyValue: any = 1;
anyValue.somethingMethod();

改成 unknown 的情境下,就嚴謹許多,也會出現錯誤。

let unknownValue: unknown = 1;
unknownValue.somethingMethod(); // 出現警告波浪~

無法重新賦值給 unknown 或 any 以外的型別

一但註記 unknown 型別,後續賦值給另外註記 unknown 與 any 變數正常不會報錯:

let unknownValue: unknown;

let foo1: unknown = unknownValue;
let foo2: any = unknownValue;

但是賦值給 unknown 或 any 以外的型別就會報錯:

let unknownValue: unknown;

let foo1: number = unknownValue;
let foo2: string = unknownValue;

需要斷言或限縮型別

一旦變數註記了 unknown,下次使用該變數就要做型別斷言或能讓編譯器做出型別檢查,目的是為了限縮型別,畢竟 unknown 表示未知,不這麼做編譯器會報錯擋著。

例如:

let anyNumber: any = 123;
let unknownNumber: unknown = 123;
anyNumber + 1; 
unknownNumber + 1; // 出現警告波浪~

unknownNumber 出現錯誤提示訊息,所以必須要給其斷言才行。

let anyNumber: any = 123;
let unknownNumber: unknown = 123;
anyNumber + 1; 
(unknownNumber as number) + 1;
// 或者
<number>unknownNumber + 1;

然而,若將上述改成 unknown 與 string 的相加

let anyString: any = "123";
let unknownString: unknown = "123";
anyString + "1";
unknownString + "1";  // 沒有警告波浪~

編譯器這邊推論給過,筆者查閱文件和網路文章沒有看到原因,後來在 FB TypeScript Taiwan 社團發問得到版主的解釋,大意如下:

 number 與 + 運算子搭配,出來的結果是不確定的,尤其是在與 unknown 不確定為合的情境下相加,自然需要斷言。
然而大部分型別用 + 運算子跟 string 型別結合都會變成 string,所以編譯器自然就給過了。

發問傳送門見此

總之,雖然 unknown 和 any 很像,但如同其他網路文章所說的,unknown 像是更安全的 any,開發者若為了自己開發習慣或要改動陳年舊 code,使用 unknown 還比使用 any 好一點。

當下次 JS 社群或靠北工程師又有反對 TS 的鄉民酸「any 啦,我都用 any」,你可以告訴他:「我都用 unknown」

參考

FB社團:TypeScript Taiwan
TypeScript 新手指南
TypeScript: Typed JavaScript at Any Scale.
kobo 電子書:讓TypeScript成爲你前端開發的ACE!
Typescript 初心者手札


#TypeScript









Related Posts

What Type of Laser Engraving Machine Should be Used for Stainless Steel Engraving?

What Type of Laser Engraving Machine Should be Used for Stainless Steel Engraving?

進入 Vue.js 前的 ES6 必備知識

進入 Vue.js 前的 ES6 必備知識

new 做了什麼事?

new 做了什麼事?


Comments