4 個 TypeScript 5.1 Beta 版重要更新內容

pingan8787發表於2023-04-26

TypeScript 5.1 在 5.0 釋出後不久就釋出了測試版,但測試版不代表最終正式版。

官方原文 Announcing TypeScript 5.1 Beta 中提供了完整的更新內容,以下是我梳理的 TypeScript 5.1 主要更新內容:

  1. 改進了函式返回值型別 undefined 的型別推斷
  2. GetterSetter 現在支援設定不同的型別
  3. 自動補全 JSDoc @param 標籤的程式碼片段
  4. TypeScript 5.1 至少需要執行在 ES2020Node.js 14.17 的執行時環境中

想要嚐鮮的朋友,可以透過 npm 快速安裝最新測試版:

npm install -D typescript@beta

1. 改進函式返回值型別 undefined 的型別推斷

在 JavaScript 中,函式如果沒有返回值,會自動返回 undefined

// no return
const test = () => {}
test();  // undefined

在早期版本的 TypeScript 中,只有返回值型別為 voidany 的函式可以沒有 return 語句,即使你清楚這個函式返回值是 undefined,你也需要至少有一個 return 語句。

//  ✅ return 'void'
const t1 = () => {}

//  ✅ 'void' doesn't need a return statement
const t2 = (): void => {}

// ✅  'any' doesn't need a return statement
const t3 = (): any => {}

// ❌ A function whose declared type is neither 'void' nor 'any' must return a value.
const t4 = (): undefined => {}

當你希望函式返回 undefined,你可以有 2 種方式:

  1. 使用 return undefined 語句;
  2. 使用 return 語句並且定義返回值型別為 undefined
declare function fun(f: () => undefined): undefined;

// ❌ Argument of type '() => void' is not assignable to parameter of type '() => undefined'.
fun(() => {})

// ❌ A function whose declared type is neither 'void' nor 'any' must return a value.
fun((): undefined => {})

// ❌ Argument of type '() => void' is not assignable to parameter of type '() => undefined'.
fun(() => {
    return;
})

// ✅ 
fun(() => {
    return undefined;
});

// ✅ 
fun((): undefined => {
    return;
});

為了解決這種困惑,TypeScript 5.1 支援允許函式返回 undefined 時不需要 return 語句。

// ✅ TypeScript 5.1!
const f1 = (): undefined => {}

// ✅ TypeScript 5.1!
f2((): undefined => {})

2. Getter 和 Setter 支援設定不同型別

在 TypeScript 4.3 允許為 GetterSetter 指定不同型別。

interface Serializer {
  set value(v: string | number | boolean);
  get value(): string;
}

declare let box: Serializer;

// ✅ Allows writing a 'boolean'
box.value = true;

// ✅ Comes out as a 'string'
console.log(box.value.toUpperCase());

// ❌ Property 'toFixed' does not exist on type 'string'.
console.log(box.value.toFixed());

最初,我們要求 get 型別必須是 set 型別的子型別,這種寫法很有效。

box.value = box.value;

但是,很多現有 API 的 GetterSetter 之間存在完全不相關的型別。例如,DOM 和 CSSStyleRule API 中的 style 屬性。每個樣式規則都有一個 CSSStyleDeclaration 型別的 style 屬性,但你只能使用字串修改它。

TypeScript 5.1 支援為 GetterSetter 設定不同型別:

interface CSSStyleRule {
  // ...

  /** Always reads as a `CSSStyleDeclaration` */
  get style(): CSSStyleDeclaration;

  /** Can only write a `string` here. */
  set style(newValue: string);

  // ...
}

也支援下面這樣使用:

class SafeBox {
  #value: string | undefined;

  // Only accepts strings!
  set value(newValue: string) {}

  // Must check for 'undefined'!
  get value(): string | undefined {
    return this.#value;
  }
}

實際上,這類似於在 --exactOptionalProperties 下檢查可選屬性的方式。

3. 自動補全 JSDoc @param 標籤的程式碼片段

TypeScript 5.1 支援在 TypeScript 和 JavaScript 檔案中輸入 @param 標記時的程式碼片段完成。幫助我們在編寫程式碼文件或在 JavaScript 中新增 JSDoc 型別時快速生成對應註釋資訊。

4. 最低執行時要求:ES2020 和 Node.js 14.17

TypeScript 5.1 支援 ECMAScript 2020 新特性,因此需要在較新的 Node.js 執行環境下使用,至少需要 Node.js 14.17 版本以上。舊版 Node.js 可能導致 tsc.jstsserver.js 執行錯誤。

node_modules/typescript/lib/tsserver.js:2406
  for (let i = startIndex ?? 0; i < array.length; i++) {
                           ^
SyntaxError: Unexpected token '?'
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

總結

TypeScript 5.1 目前還在測試階段,預計會在接下來的幾周內釋出候選版本和最終穩定版本。如果你對 TpeScript 感興趣,可以安裝測試版嘗試體驗一下。

相關文章