TypeScript 新品嚐鮮

還記得我在《2020 年 JavaScript 狀態調研報告小結》中提到的 2020 年全球開發者最喜歡的 JavaScript 寫法是什麼嗎?-- 沒錯!TypeScript!。鑑於在項目中使用 TypeScript 確實有如下種種好處:html

  1. 幫助開發者在「運行時」而非「編譯時」及時感知類型/語法錯誤(⚠️ 注意,TypeScript 並不是萬能,它並不能幫助您捕捉請求錯誤或環境錯誤);
  2. 結合編輯器,提供智能提示,提高開發體驗;
  3. 不多被說起的一點:更容易讓服務端程序員理解代碼,方便先後端交流;

本篇文章將向您介紹 TypeScript 自 3.7 版本以來更新的一些實用特性,但願您的代碼能變得更加穩固,優雅。git

1. 新支持特性

請注意,TypeScript 是 JavaScript 類型的超集,而非語法的超集,所以一些符合 JavaScript 語法規範的代碼,在 TypeScript 中卻可能報錯,例如:程序員

let x = 1
x = 'hello world'

所以,在現代工具鏈中,TypeScript 編譯器甚至不被用做編譯出指定版本 JavaScript 的工具(這一般是 babel 的工做),而是做爲一種更強大的代碼檢查工具被使用。可是隨着 TypeScript 版本的更新,一些新的 JavaScript 語法特性也逐漸被 TypeScript 支持,這使得開發者在一些場景下能夠擺脫 babel 編譯的過程,直接使用 TypeScript 編譯生成最終的代碼。github

1.1 Optional Chaining & Nullish Coalescing

自 3.7 版本開始,TypeScript 支持了目前在 stage 4 階段的 Optional ChainingNullish Coalescing語法。typescript

1.2 Private Fields && Namespace exports

自 3.8 版本開始,Typescript 支持了目前在 stage 3 階段的 Private Fields 語法。(經過底層使用 WeakMap 數據結構,該語法使得 JavaScript 類真正意義上擁有「私有屬性」)編程

class Foo {
  #bar
}

同時,該版本還支持了 namespace exports 語法:後端

export * as utils from './utils'

1.3 Inference of class field types

自 4.0 版本開始,TypeScript 支持自動推導 class 中的屬性類型,無需再顯示聲明。babel


2. 新類型:元組

TypeScript 4.0 開始支持兩種新的元組類型聲明方式:數據結構

  1. Variadic tuple types(可變元組類型)
  2. Labeled tuple types(命名元組類型)

2.1 可變元組類型

type Foo<T extends any[]> = [boolean, ...T, boolean]

經過這種聲明方式,咱們能夠更精確的定義一個函數參數類型,在使用函數式編程時,這種定義方式就頗有用。編輯器

2.2 命名元組類型

const Address = [string, number]

function setAddress(...args: Address) {
  // some code here
}

當咱們這樣定義函數入參後,在使用函數時,編輯器的智能提示只會提示咱們參數類型,丟失了對參數含義的描述。爲了改善這一點,咱們能夠經過 Labeled tuple types,咱們能夠這樣定義參數:

const Address = [streetName: string, streetNumber: number]

function setAddress(...args: Address) {
  // some code here
}

這樣,在調用函數時,咱們的參數就得到了相應的語義,這使得代碼更加容易維護。


3. 可遞歸調用類型

自 Typescript 3.7 開始,咱們終於得到了只用一條類型聲明聲明 JSON 數據的能力:

type JSONValue = 
  | string
  | number
  | boolean
  | null
  | JSONValue[]
  | {
      [key: string]: JSONValue
    }

4. 錯誤和斷言處理

4.1 // @ts-expect-error

TypeScript 3.9 給出了一個替代 // @ts-ignore 註釋的方案:// @ts-expect-error

從字面上咱們不難理解爲何後者是更優的選擇:

  1. 顯示聲明瞭會報錯的緣由,而不僅是一味的規避檢查;
  2. 向前兼容,將來若是 TypeScript 支持某語法致使再也不報錯,TypeScript 會主動提示刪除註釋,這會讓代碼變得更加簡潔;

4.2 unknown 類型

讓咱們想一想這段代碼會最終打印出什麼:

try {
  willThrowAnError()
} catch (err) {
  console.log(typeof err.message)
}

答案是 "string" 嗎,並不是如此!由於 err.message 的值有多是 undefined,甚至有可能在這裏拋錯,這取決於咱們的函數 willThrowAnError 內部是如何定義的:

// err.message => undefined
function willThrowAnError() {
    throw 'hello world'
}

// err.message => throw an Error!
function willThrowAnError() {
  throw null
}

雖然第二種狀況幾乎不會發生,但這兩個示例說明了 catch 參數類型的不肯定性(所以在 TypeScript 中,它的默認類型是 any)。

所以,在 TypeScript 4.0 中,提供了 unknown 類型供咱們處理這些咱們「不知道」的類型。不一樣於 any 類型,unknown 是 TypeScript 中的第一類型,能夠在任何地方使用。

子曰:知之爲知之,不知爲不知。

4.3 Assertion functions

自 TypeScript 3.7 開始,支持基於 return/throw 的類型斷言。

function assertIsArray(val: any): asserts val is any[] {
  if (!Array.isArray(val)) throw new Error(`${val} is not an array`)
}

這將讓測試變得更加容易。

點擊此處瀏覽相關文檔


5. 模塊

5.1 Type-only imports

自 TypeScript 3.8 開始,TypeScript 支持僅引入模塊類型:

import type { SomeThing } from "./some-module.js";

export type { SomeThing };

這樣作的好處在於,當某個模塊中包含反作用代碼時,用戶若是直接引入模塊,就會無心間執行反作用代碼,但當經過聲明只引入類型時,則避免了這個隱患。

點擊此處瀏覽相關文檔

6. 小結

至此,本篇文章帶您快速瀏覽了 TypeScript 3.7 以來一些實用性強的新特性,不知道您是否學有所獲?TypeScript 將在 2021 年 5 月 25 日發佈 4.3 版本,屆時會新增哪些有意思的新特性?且聽下回分解:)

相關文章
相關標籤/搜索