TypeScript 2.4

動態匯入表示式 (Dynamic Import Expressions)

動態 import 表示式是一項新功能,屬於 ECMAScript 的一部分,允許使用者在程式的任何位置非同步請求模組。

這意味著你可以按條件和延遲匯入其他模組和庫。例如,下面是一個 async 函式,它僅在需要時才匯入實用工具庫:

ts
async function getZipFile(name: string, files: File[]): Promise<File> {
const zipUtil = await import("./utils/create-zip-file");
const zipContents = await zipUtil.getContentAsBlob(files);
return new File(zipContents, name);
}

許多打包工具支援根據這些 import 表示式自動拆分輸出包,因此請考慮將此新功能與 esnext 模組目標一起使用。

字串列舉 (String Enums)

TypeScript 2.4 現在允許列舉成員包含字串初始化表示式。

ts
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}

需要注意的是,字串初始化的列舉無法進行反向對映以獲取原始列舉成員名稱。換句話說,你不能透過 Colors["RED"] 來獲取字串 "Red"

改進了泛型推斷

TypeScript 2.4 針對泛型推斷的方式引入了一些極好的改進。

將返回型別作為推斷目標

首先,TypeScript 現在可以針對呼叫的返回型別進行推斷。這可以改善你的開發體驗並捕獲錯誤。以下程式碼現在可以正常工作:

ts
function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[] {
return a => a.map(f);
}
const lengths: (a: string[]) => number[] = arrayMap(s => s.length);

作為這一變動可能導致的新錯誤示例:

ts
let x: Promise<string> = new Promise(resolve => {
resolve(10);
// ~~ Error!
});

基於上下文型別的型別引數推斷

在 TypeScript 2.4 之前,在以下示例中:

ts
let f: <T>(x: T) => T = y => y;

y 的型別將為 any。這意味著程式可以透過型別檢查,但你實際上可以對 y 進行任何操作,例如:

ts
let f: <T>(x: T) => T = y => y() + y.foo.bar;

最後一個示例實際上並不是型別安全的。

在 TypeScript 2.4 中,右側的函式隱式獲得了型別引數,並且 y 被推斷為該型別引數的型別。

如果你以型別引數的約束不支援的方式使用 y,你將正確地獲得一個錯誤。在這種情況下,T 的約束(隱式地)為 {},因此最後一個示例將適當地報錯。

泛型函式更嚴格的檢查

TypeScript 現在嘗試在比較兩個單簽名型別時統一型別引數。因此,你在關聯兩個泛型簽名時會得到更嚴格的檢查,並可能捕獲一些 Bug。

ts
type A = <T, U>(x: T, y: U) => [T, U];
type B = <S>(x: S, y: S) => [S, S];
function f(a: A, b: B) {
a = b; // Error
b = a; // Ok
}

回撥引數的嚴格逆變 (Strict Contravariance)

TypeScript 一直以雙向協變的方式比較引數。這有多種原因,但總的來說,在我們看到它對 PromiseObservable 產生的一些負面影響之前,這並不是使用者的主要困擾。

TypeScript 2.4 在關聯兩個回撥型別時加強了這一點。例如:

ts
interface Mappable<T> {
map<U>(f: (x: T) => U): Mappable<U>;
}
declare let a: Mappable<number>;
declare let b: Mappable<string | number>;
a = b;
b = a;

在 TypeScript 2.4 之前,這個示例會成功。當關聯 map 的型別時,TypeScript 會雙向關聯它們的引數(即 f 的型別)。當關聯每個 f 時,TypeScript 也會雙向關聯那些引數的型別。

在 TS 2.4 中關聯 map 的型別時,語言將檢查每個引數是否為回撥型別;如果是,它將確保這些引數相對於當前關係以逆變的方式進行檢查。

換句話說,TypeScript 現在可以捕獲上述 Bug,這對於某些使用者來說可能是破壞性變更,但總體上是有幫助的。

弱型別檢測 (Weak Type Detection)

TypeScript 2.4 引入了“弱型別”的概念。任何只包含可選屬性的型別都被視為弱型別。例如,這個 Options 型別就是一個弱型別:

ts
interface Options {
data?: string;
timeout?: number;
maxRetries?: number;
}

在 TypeScript 2.4 中,當沒有屬性重疊時,將任何內容分配給弱型別現在會報錯。例如:

ts
function sendMessage(options: Options) {
// ...
}
const opts = {
payload: "hello world!",
retryOnFail: true
};
// Error!
sendMessage(opts);
// No overlap between the type of 'opts' and 'Options' itself.
// Maybe we meant to use 'data'/'maxRetries' instead of 'payload'/'retryOnFail'.

你可以將此視為 TypeScript 在“加強”這些型別的弱保證,以捕獲原本會悄無聲息發生的 Bug。

由於這是一個破壞性變更,你可能需要了解解決方法,這些方法與嚴格物件字面量檢查的解決方法相同:

  1. 如果屬性確實存在,請宣告這些屬性。
  2. 向弱型別新增索引簽名(即 [propName: string]: {})。
  3. 使用型別斷言(即 opts as Options)。

TypeScript 文件是一個開源專案。請透過 傳送 Pull Request 幫助我們改進這些頁面 ❤

此頁面的貢獻者
DRDaniel Rosenwasser (52)
OTOrta Therox (12)
2+

最後更新:2026 年 3 月 27 日