TypeScript 中 unknown 與 any 有啥區別

前端小智發表於2021-10-28
作者:Ashish Lahoti
譯者:前端小智
來源:dmitripavlutin

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

我們知道 any 型別的變數可以被賦給任何值。

let myVar: any = 0;
myVar = '1';
myVar = false;

TypeScript 指南並不鼓勵使用 any,因為使用它就會丟掉型別限制--而需要型別限制也是我們選擇 TypeScript 的一個原因,所以就是有點背道而馳。

TypeScript(3.0 及以上版本)還提供了一種類似於 any 的特殊型別 unknown。 我們也可以為 unknown 型別變數分配任何值:

let myVar: unknown = 0;
myVar = '1';
myVar = false;

那現在就有一個問題了, anyunknown 有啥區別?

1. unknown vs any

為了更好地理解 unknownany 之間的區別,我們先從編寫一個想要呼叫其唯一引數的函式開始。

我們將 invokeAnything() 的唯一引數設定為 any 型別

function invokeAnything(callback: any) {
  callback();
}

invokeAnything(1); // throws "TypeError: callback is not a function"

因為 callback 引數是任何型別的,所以語句 callback() 不會觸發型別錯誤。我們可以用any 型別的變數做任何事情。

但是執行會丟擲一個執行時錯誤:TypeError: callback is not a function1 是一個數字,不能作為函式呼叫,TypeScript並沒有保護程式碼避免這個錯誤

那既允許 invokeAnything() 函式接受任何型別的引數,又要強制對該引數進行型別檢查防止上面這種報錯,要怎麼做呢?

有請 unknown 大哥來控場。

any 一樣,unknown 變數接受任何值。但是當嘗試使用 unknown 變數時,TypeScript 會強制執行型別檢查。這不就是我們想要的嘛。

function invokeAnything(callback: unknown) {
  callback();
  // Object is of type 'unknown'
}

invokeAnything(1);

因為 callback 引數的型別是 unknown,所以語句 callback() 有一個型別錯誤 :Object is of type 'unknown'。 與 any 相反,TypeScript會保護我們不呼叫可能不是函式的東西。

在使用一個 unknown 型別的變數之前,你需要進行型別檢查。在這個例子中,我們只需要檢查callback 是否是一個函式型別。

function invokeAnything(callback: unknown) {
  if (typeof callback === 'function') {
    callback();
  }
}

invokeAnything(1);

2. unknown 和 any 的心智模式

說實話,當我學習的時候,我很難理解 unknown 。它與 any 有什麼不同,因為這兩種型別都接受任何值

下面是幫助我理解兩者區別的規則:

  • 可以將任何東西賦給 unknown 型別,但在進行型別檢查或型別斷言之前,不能對 unknown 進行操作
  • 可以把任何東西分配給any型別,也可以對any型別進行任何操作

上面的例子正好說明了 unknown 和 `any 之間的相似和不同。

unknown 示例:

function invokeAnything(callback: unknown) {
  // 可以將任何東西賦給 `unknown` 型別,
  // 但在進行型別檢查或型別斷言之前,不能對 `unknown` 進行操作
  if (typeof callback === 'function') {
    callback();
  }
}

invokeAnything(1); // You can assign anything to `unknown` type

型別檢查 typeof callback === 'function',檢查 callback 是否為函式,如果是,則可以呼叫。

any 示例:

function invokeAnything(callback: any) {
  // 可以對 `any` 型別執行任何操作
  callback();
}

invokeAnything(1); // 可以把任何東西分配給`any`型別

如果 callbackany, TypeScript 就不會強制 callback() 語句進行任何型別檢查。

3.總結

unknownany 是2個特殊的型別,可以容納任何值。

推薦使用 unknown 而不是 any,因為它提供了更安全的型別--如果想對 unknown 進行操作,必須使用型別斷言或縮小到一個特定的型別。

~~ 完,我是小智,女票在教培行業工作,最近發的工資有點低,我準備多多下海工作,賺更多的錢了。


編輯中可能存在的bug沒法實時知道,事後為了解決這些bug,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原文:https://dmitripvlutin.com/typ...

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章