TypeScript 3.7 帶來了哪些好用的功能

TypeScript 3.7 帶來了哪些好用的功能

Optional Chining(可選鏈)

Optional Chining 核心點在於它允許我們寫出在遇到 null 或者 undefined 時,能立即停止運行的代碼。

其語法爲 ?. ,可以用該運算符來訪問一個對象中的可選屬性。

現在看下面的代碼

let x = foo?.bar.baz();

這行代碼表示的意思是:當 foo 存在(即該變量不爲 null 或 undefined),那麼表達式 foo?.bar.baz() 執行完成;反之,當 foonullundefined 時,TypeScript會立即停止運行,並返回 undefined

用代碼表達上面這句話的意思即爲:

let x = (foo === null || foo === undefined) ? undefined : foo.bar.baz();

**注意:**我們只對 foo 做了可選鏈的檢測,那麼當 barnullundefined 時,代碼仍然是會報錯的,同理 baz 也一樣 。

Optional Chining 帶來的好處是顯而易見的,它會使得代碼更加的簡練並輕鬆替換掉一寫前置判斷條件。

比如:

// 之前的前置判斷大多是這麼寫的
if (foo && foo.bar && foo.bar.baz) {
    // ...
}

// 使用 Optional Chining 後
if (foo?.bar?.baz) {
    // ...
}

在大多數情況下 &&?. 是可以替換的,但是兩者之間的行爲略有不同,不同點如下:

  • && 專用於假值(”falsy“),如 false | "" | 0 | null | undefined

  • ?.則是針對於null | undefined` 的判斷

Optional Chining 除了可用於可選屬性的訪問,還可用於可選元素的訪問,以及可選調用的訪問。

// 可選元素->獲取數組的第一個元素
function getFirstElement<T>(arr?: T[]) {
    return arr?.[0];
}

// 可選調用->函數調用
function wrapFn(fn?: (msg: string) => void) {
  fn?.('test');
}

注意:Optional Chining 的「短路運算」行爲被侷限在屬性的訪問、函數的調用以及元素的訪問,它不會沿伸到後續的表達式中

看下面的代碼

let result = foo?.bar / someComputation()

Optional Chining 不會阻止除法運算或者 someComputation() 調用。


Nullish Coalescing

運算符 ?? 有點類似於默認值得處理方式,當處理 nullundefined 時,便會使用默認值。

let x = foo ?? bar();
// 等價於
let x = (foo !== null && foo !== undefined) ? foo : bar();

這行代碼表示:當 foo 值存在時,foo 會被使用,但是當它是 nullundefined,它會執行 bar()

?? 運算符出現之前,我們對默認值處理是使用 ||

比如:

// window.volume 爲 0 時,則取值 0.5,而在使用 ?? 時 則取值爲 0
let volume = window.volume || 0.5; 

Optional Chining 類似,運算符 ??|| 在默認值的取值上區別在於

  • || 判斷範圍爲(”falsy“),如 false | "" | 0 | null | undefined
  • ?? 則是針對於 null | undefined 的判斷

--declaration and --allowJs

--declaration 選項可以讓我們從 TypeScript 源文件(如 .ts.tsx 文件)中生成 .d.ts 聲明文件。

--allowJs 選項允許TypeScript解析 .jsjsx 文件。

然而在 3.7 之前的版本中,兩者並不能一起使用,因爲 --declaration 選項會混合 TypeScript 和 JavaScript 輸入文件。

在 TypeScript 3.7 中,兩者可以一起使用,用戶通過在 JavaScript 庫中寫的 JSDoc 註釋,能幫助 TypeScript 用戶進行類型檢查。

const assert = require('assert');

module.exports.blurImage = blurImage;

/**
 * Produces a blurred image from an input buffer.
 *
 * @param input {Uint8Array}
 * @param width {number}
 * @param height {number}
 */
function blurImage(input, width, height) {
  const numPixels = width * height * 4;
  assert(input.length === numPixels);
  const result = new Uint8Array(numPixels);

  // TODO

  return result;
}

將會產生如下的 .d.ts

/**
 * Produces a blurred image from an input buffer.
 *
 * @param input {Uint8Array}
 * @param width {number}
 * @param height {number}
 */
export function blurImage(input: Uint8Array, width: number, height: number): Uint8Array;

以上爲個人認爲在 TypeScript 3.7 中需要重點關注的內容,其他具體內容見 TypeScript 3.7 更新概覽


TypeScript 3.8 中值得關注的功能

  1. ECMAScript 私有字段

    • class Person {
          #name: string
      
          constructor(name: string) {
              this.#name = name;
          }
      
          greet() {
              console.log(`Hello, my name is ${this.#name}!`);
          }
      }
      
      let jeremy = new Person("Jeremy Bearimy");
      
      jeremy.#name
      //     ~~~~~
      // Property '#name' is not accessible outside class 'Person'
      // because it has a private identifier.
      
  2. export * as ns 語法

    • export * as utilities from "./utilities.js";
      
    • 上面代碼在 ECMAScript 2020 中被支持,TypeScript 3.8 實現了此語法

  3. Top-Level await

    • 在當前的 JavaScript 中(以及其他具有相似功能的大多數其他語言),await 僅僅只能用於 async 函數內部。然而,使用 top-level await 時,我們可以在一個模塊的頂層使用 await
  4. watchOptions 配置監聽策略

具體細節見 TypeScript 3.8 Beta

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章