(譯)【TypeScript 演化史 -- 9】object 類型 和 字符串索引簽名類型的點屬性

做者:Marius Schulzhtml

譯者:前端小智前端

來源:mariusschulz.com/git

點贊再看,養成習慣
es6


本文 GitHub:github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。github

我的專欄 ES6 深刻淺出已上線,深刻ES6 ,經過案例學習掌握 ES6 中新特性一些使用技巧及原理,持續更新中,←點擊可訂閱。面試

系列文章以下:typescript

【TypeScript 演化史 -- 1】non-nullable 的類型數據結構

【TypeScript 演化史 -- 2】基於控制流的類型分析 和 只讀屬性app

【TypeScript 演化史 -- 3】標記聯合類型 與 never 類型async

【TypeScript 演化史 -- 4】更多的字面量類型 與 內置類型聲明

【TypeScript 演化史 -- 5】將 async/await 編譯到 ES3/ES5 (外部幫助庫)

【TypeScript 演化史 -- 6】對象擴展運算符和 rest 運算符及 keyof 和查找類型

【TypeScript 演化史 -- 7】映射類型和更好的字面量類型推斷

【TypeScript 演化史 -- 8】字面量類型擴展 和 無類型導入

TypeScript 2.2 引入了一個新的 object 類型。它表示任何非基本類型。如下是 JS 的基本類型:

  • string
  • boolean
  • number
  • bigint
  • symbol
  • null
  • undefined

上述之外類型都被認爲是非基本類型,能夠用新的 object 類型表示:

// 全部基本類型
type Primitive =
  | string
  | boolean
  | number
  | bigint
  | symbol
  | null
  | undefined;

// 全部非基本類型
type NonPrimitive = object;
複製代碼

使用 object 類型的類型聲明

隨着 TypeScript 2.2 的發佈,標準庫的類型聲明已經更新,以使用新的 object 類型。例如,object.create()object.setprototypeof() 方法現的參數類型是 object | null

interface ObjectConstructor {

  create(o: object | null): any;

  setPrototypeOf(o: any, proto: object | null): any;

  // ...
}
複製代碼

將基本類型的值做爲參數傳遞給 Object.setPrototypeOf()Object.create() 會致使在運行時拋出類型錯誤。TypeScript 如今捕獲這些錯誤並在編譯時提示錯誤:

const proto = {};

Object.create(proto);     // OK
Object.create(null);      // OK
Object.create(undefined); // Error
Object.create(1337);      // Error
Object.create(true);      // Error
Object.create("oops");    // Error
複製代碼

object 類型的另外一個用例是 ES6 引入的 WeakMap 數據結構。它的鍵必須是對象,不能是基本類型值:

interface WeakMap<K extends object, V> {
  delete(key: K): boolean;
  get(key: K): V | undefined;
  has(key: K): boolean;
  set(key: K, value: V): this;
}
複製代碼

object vs Object vs {}

可能使人困惑的是,TypeScript定義了幾個具備類似名稱但表示不一樣概念的類型:

  • object
  • Object
  • {}

上面已經講過 object 類型,如今來看看 Object{}

Object 類型

TypeScript 定義了另外一個與新 object 類型幾乎同名的類型,那就是 Object 類型。object (小寫)表示全部非基本類型,而 Object (大寫)描述全部 JS 對象共有的功能。例如,它包括 toString()hasOwnProperty() 方法。

在TypeScript附帶的lib.es6.d.ts文件中,Object類型定義以下:

interface Object {
  // ...

  /** Returns a string representation of an object. */
  toString(): string;

  /** Returns a date converted to a string using the current locale. */
  toLocaleString(): string;

  /** Returns the primitive value of the specified object. */
  valueOf(): Object;

  /**
   * Determines whether an object has a property with the specified name.
   * @param v A property name.
   */
  hasOwnProperty(v: string): boolean;

  /**
   * Determines whether an object exists in another object's prototype chain.
   * @param v Another object whose prototype chain is to be checked.
   */
  isPrototypeOf(v: Object): boolean;

  /**
   * Determines whether a specified property is enumerable.
   * @param v A property name.
   */
  propertyIsEnumerable(v: string): boolean;
}
複製代碼

空類型 {}

還有另外一種類型與之很是類似:{},即空類型。它描述了一個自己沒有成員的對象。當我們試圖訪問此類對象上的任意屬性時,TypeScript 會提示編譯時錯誤

// Type {}
const obj = {};

// Error: 類型「{}」上不存在屬性「prop」
obj.prop = "value";
複製代碼

可是,仍然可使用在 Object 類型上定義的全部屬性和方法,這些屬性和方法經過JS 的原型鏈調用:

// Type {}
const obj = {};

// "[object Object]"
obj.toString();
複製代碼

字符串索引簽名類型的點屬性

在 TypeScript 2.2 以前,若是想訪問帶有字符串索引簽名的類型的任意屬性,就必須使用[]符號,但不容許使用.符號訪問

interface Dictionary<T> {
  [key: string]: T;
}

const portNumbers: Dictionary<number> = {};

// OK
portNumbers["http"] = 80;

// Error: Property 'http' does not exist on type 'Dictionary<number>'.
portNumbers.http = 80;
複製代碼

TypeScript 2.2 取消了這個限制。如今可使用 []. 符號訪問屬性。在許多狀況下,再也不須要像這樣使人不快的變通方法:

// 笨拙的方式
(portNumbers as any).http = 80;
複製代碼

請注意,類型必須定義顯式字符串索引簽名,以便用.符號訪問對任意屬性都是類型正確的。在類型使用上使用.符號訪問未知屬性仍然是一個錯誤,所以,對於如下代碼,TypeScript 2.2 仍然會給出一個編譯時錯誤:

const portNumbers = {};

// OK
portNumbers["http"] = 80;

// Error: Property 'http' does not exist on type '{}'.
portNumbers.http = 80;
複製代碼

若是仔細想一想,就會發現這頗有意義:若是 TypeScript 沒有爲這段代碼提供一個錯誤,那麼就沒有對拼寫錯誤的屬性名的保護。在 JS 中訪問屬性時,大多數時候將使用表示法,但也可使用括號表示法做爲轉義。

有了這個較鬆的限制,對於經常使用JS 開發的人員來講更容易使用。若是我們要將現有的 JS 代碼基礎遷移到 TypeScript,這尤爲有用。給定適當的字符串索引簽名,在這些狀況下,就會得到更少的類型錯誤,而且再也不須要使用類型註釋註釋點屬性訪問,這只是爲了讓編譯器經過。


原文:

mariusschulz.com/blog/the-ob…

mariusschulz.com/blog/dotted…


交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

github.com/qq449245884…

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

clipboard.png
相關文章
相關標籤/搜索