TypeScript 中的頂級類型:any 和 unknown

做者:Dr. Axel Rauschmayer

翻譯:瘋狂的技術宅html

原文:https://2ality.com/2020/06/an...前端

未經容許嚴禁轉載程序員

在 TypeScript中,anyunknown 是包含全部值的類型。在本文中,咱們將會研究它們是怎樣工做的。面試


TypeScript 的兩種頂級類型

any and unknown are so-called top types in TypeScript. Quoting Wikipedia:typescript

anyunknown 在 TypeScript 中是所謂的「頂部類型」。如下文字引用自 Wikipediasegmentfault

top type [...]是 通用(universal) 類型,有時也稱爲 通用超類型,由於在任何給定類型系統中,全部其餘類型都是子類型[...]。一般,類型是包含了其相關類型系統中全部可能的[值]的類型。

也就是說,當把類型看做是值的集合時,anyunknown 是包含全部值的集合。順便說一句,TypeScript 還有 bottom type never,它是空集。數組

頂級類型 any

若是一個值的類型爲 any,那麼咱們就能夠用它任何事:安全

function func(value: any) {
    // 僅容許數字,但它們是 `any` 的子類型
    5 * value;

    // 一般,`value` 的類型簽名必須包含 .propName
    value.propName;

    // 一般只容許帶有索引簽名的數組和類型
    value[123];
}

任何類型的值均可以賦值給 any 類型:服務器

let storageLocation: any;

storageLocation = null;
storageLocation = true;
storageLocation = {};

類型 any 也可被可賦值給每一種類型:微信

function func(value: any) {
    const a: null = value;
    const b: boolean = value;
    const c: object = value;
}

使用 any,咱們將會失去一般由 TypeScript 的靜態類型系統所給予的全部保護。所以,若是咱們沒法使用更具體的類型或 unknown,則只能將其用做最後的手段。

示例:JSON.parse()

JSON.parse() 的結果取決於動態輸入,這就是其返回類型爲 any 的緣由(我從函數簽名中省略了參數 reviver):

JSON.parse(text: string): any;

unknown 類型出現以前,JSON.parse() 就已經被添加到了 TypeScript中。不然它的返回類型可能會是 unknown

示例:String()

把任意值轉換爲字符串的函數 String() 具備如下類型簽名:

interface StringConstructor {
    (value?: any): string; // call signature
    // ···
}

頂級類型 unknown

unknown 類型是 any 的類型安全版本。每當你想使用 any 時,應該先試着用 unknown

any 容許咱們作任何事的地方,unknown 的限制則大得多。

在對 unknown 類型的值執行任何操做以前,必須先經過如下方法限定其類型:

  • 類型斷言
function func(value: unknown) {
  // @ts-ignore: Object is of type 'unknown'.
  value.toFixed(2);

  // Type assertion:
  (value as number).toFixed(2); // OK
}
  • 相等:
function func(value: unknown) {
  // @ts-ignore: Object is of type 'unknown'.
  value * 5;

  if (value === 123) { // equality
      // %inferred-type: 123
      value;

      value * 5; // OK
  }
}
  • 類型防禦:
function func(value: unknown) {
  // @ts-ignore: Object is of type 'unknown'.
  value.length;

  if (typeof value === 'string') { // type guard
      // %inferred-type: string
      value;

      value.length; // OK
  }
}
  • 斷言函數:
function func(value: unknown) {
  // @ts-ignore: Object is of type 'unknown'.
  value.test('abc');

  assertionFunction(value);

  // %inferred-type: RegExp
  value;

  value.test('abc'); // OK
}

function assertionFunction(arg: unknown): asserts arg is RegExp {
  if (! (arg instanceof RegExp)) {
      throw new TypeError('Not a RegExp: ' + arg);
  }
}

本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索