TypeScript 5.3将带来哪些新内容
TypeScript 5.2 已经发布,团队已经在努力开发 TypeScript 5.3。他们最近发布了TypeScript 5.3 迭代计划,该文档用于规划下一版本 TypeScript 中可能包含的功能。
迭代计划是了解 TypeScript 5.3 即将推出的内容的好方法。这并不能保证这些功能一定会落地——但这是一个很好的迹象。所以 - 这是我对 TS 5.3 中可能出现的最有趣功能的总结。
Import 属性
TypeScript 5.3 可能会实现导入属性(Import Attributes),这是最近达到第 3 阶段的 TC39 提案。
导入属性允许您指定导入选项。例如,您可以指定 JSON 导入的类型:
import json from './foo.json' with { type: 'json' };它还允许您指定动态导入的类型:
import("foo.json", { with: { type: "json" } });您可以重新导出具有经过验证的类型的模块:
export { val } from './foo.js' with { type: "javascript" };或者,使用经过验证的类型实例化一个工作线程:
new Worker("foo.wasm", { type: "module", with: { type: "webassembly" },});此更改的动机是为 JavaScript 提供一种方法来验证正在导入的 MIME 类型类型。主要原因是安全性:“防止响应服务器意外提供不同的 MIME 类型,从而导致代码意外执行”。
支持throw表达式
为 JavaScript 提出的语法之一是表达式throw。这是一种不使用语句抛出错误的方法。例如,你可以写:
const id = searchParams.id || throw new Error("id is required");您可能会感到惊讶,今天的 JavaScript 中还没有这种功能 - 但事实并非如此!它会在 TypeScript 中抛出错误:
const id =searchParams.id || thrownew Error( "id is required");
Expression expected.
然而,抛出表达式不太可能出现在 TypeScript 5.3 中。该提案仍处于第 2 阶段,距离将它们添加到 TypeScript 所需的第 3 阶段基准还有一点距离。
但 TypeScript 迭代计划特别提到“支持”这一提案。这意味着他们正在积极研究它,因此它可能会出现在 JavaScript/TypeScript 的未来版本中。
Isolated Declarations
几周前,我有幸有机会前往彭博社伦敦办公室,与这篇公关的作者(Titian)进行了交谈。我对此感到非常兴奋。
在包含许多包的 monorepo 中,您可能拥有相互依赖的包。您最终可能会得到一个非常深的、类似“家谱”的设置,其中包 A 依赖于包 B,包 B 又依赖于包 C,包 C 又依赖于包 D。
在这些情况下,TypeScript 的检查可能会变得相当慢。必须先检查 D 包,然后是 C 包,然后是 B,然后是 A。
原因是每个包的打印声明文件(.d.ts 文件)必须由 TypeScript 本身完成 - 这也意味着对它们进行类型检查。这是一个缓慢的过程。
加快速度的一种方法是让更快的工具(例如esbuild或swc)为每个包创建声明文件。但这目前是不可能的。TypeScript 对于需要添加到代码中的注释的数量相当宽松。第三方工具不够智能,无法根据推理生成声明文件。
输入隔离声明- 一种新的、更严格的 TypeScript 模式可以解决这个问题。
您可以将其添加到您的tsconfig.json:
{ "compilerOptions": { "isolatedDeclarations": true }}启用后,它将迫使您更加严格地添加注释。确切的严格程度仍在制定中,可能会随着时间的推移而改变。但举个例子,导出函数的返回类型注释可能是强制性的,以使 TypeScript 不必推断它们。
在您大惊小怪之前(我有记录表明我非常不喜欢返回类型注释),您只需要isolatedDeclarations在共享包上启用它 - 您不需要在应用程序代码上启用它。对共享包的限制可能是可取的,因为通常您无论如何都希望向共享包添加更多注释。
Titian 和团队最近的演示显示了大型单一存储库的显着加速。我很高兴看到这是否会出现在 TypeScript 5.3 中。
在泛型函数中缩小类型
我对使用泛型函数的一个建议是“不要害怕使用as”。现有的 TypeScript 在泛型函数内部缩小类型方面表现不佳。 看看下面的例子。

在这里,我们尝试根据键从对象返回值。如果我们传入“foo”,我们将返回一个字符串。如果我们传入“bar”,我们将返回一个数字。
但是 TypeScript 给出了一个错误,尽管这段代码看起来是有效的。
这种情况没有发生的原因是 TypeScript 没有缩小 Example[T]为正确的键。任何缩小范围Example[T]都会导致其被输入为never- 因此会出现上述错误。
当前实现此功能的唯一方法是输入as never:
function exampleFunc<T extends keyof Example>(key: T): Example[T] {
if (key === 'foo') {
return 'abc' as never;
} else {
return 123 as never;
}
}这感觉真的非常非常糟糕。
TypeScript 5.3可能会在此处进行一些更改。有一个长期悬而未决的问题详细说明了这一变化的动机。
这可能是我最兴奋的事情 - 这里错误的推论对人们尝试泛型来说是一个巨大的障碍。如果 TypeScript 在这些情况下更聪明,那将使我教授泛型的工作变得更加容易。
字符串的宽松自动补全
TypeScript 有一个著名的 hack,你可以使用 astring & {}在字符串上获得“松散自动完成”。例如:
type <>IconSize = | "small" | "medium" | "large" | (string & {});此注释可能看起来很奇怪 - 但它存在的原因是您可以传递任何内容,IconSize同时还可以自动完成其他三个值。
const <>icons: <>IconSize[] = [ "small", "medium", "large", "extra-large", "anything-goes",];TypeScript 5.3 可能会推出一项新功能,使这种黑客攻击变得不必要。您将能够用作string类型并获得相同的自动完成功能:
type <>IconSize = | "small" | "medium" | "large" | string;这将是非常受欢迎的——特别是因为 Webstorm 用户已经拥有这个多年了。
@types/node中的fetch
2022 年 2 月 1 日,Node.js 团队合并了一个拉取请求,将 Fetch api 添加到 Node.js。这意味着Node.js将拥有一个fetch功能,就像浏览器一样。
这个小问题导致了一个相对激烈的DefinitelyTyped issue讨论。
参考:https://www.totaltypescript.com/typescript-5-3
本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!