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 日