TypeScript 3.5 发布了,此版本在编译器、语言和编辑器工具上带来了一些新特性。
TypeScript 3.5 引入了几种对于 type 检查和增量构建的优化,使得速度大幅提升。
type 检查加速
TypeScript 3.4 中的意外地引入了一个回退,它可能导致 type 检查器执行的工作量增加,并增加相应的 type 检查时间,这使得使用样式组件库的用户受到较大的影响。
该回退非常严重,不仅因为它导致 TypeScript 代码的构建时间变长很多,也使得 TypeScript 与 JavaScript 用户的编辑器操作变得很慢。
此版本重点关注优化了某些代码路径并将某些功能剥离,使得 TypeScript 3.5 在进行许多增量检查的时候比 TypeScript 3.3 更快。与 3.4 相比,不仅编译时间减少,而且代码自动补全与任何其它编辑器操作也变得更快。
--incremental 改进
TypeScript 3.4 引入了一个新的 --incremental 编译器选项,此选项将一堆信息保存到 .tsbuildinfo 文件中,该文件可用于加快对 tsc 的后续调用。
3.5 版本中有几个优化用来缓存编译器设置状态、查找文件的原因,以及找到文件的位置等信息。测试结果表示,在 --build 模式下使用 TypeScript 的项目引用的数百个场景中,与 TypeScript 3.4 相比,重新构建时间可减少 68%。
很多时候,我们想要创建一个省略某些属性的对象,TypeScript 内置的 Pick 和 Exclude helper 可以完成类似的功能。例如,如果我们想要定义一个没有 location 属性的 Person,可以编写以下内容:
type Person = {
name: string;
age: number;
location: string;
};
type RemainingKeys = Exclude<keyof Person, "location">;
type QuantumPerson = Pick<Person, RemainingKeys>;
// equivalent to
type QuantumPerson = {
name: string;
age: number;
};
这里使用 Exclude helper type 从 Person 的属性集中去掉了“location”属性,之后使用 Pick helper type 从 Person 中选中剩下的属性集。
这种 type 的操作经常出现,用户将编写一个 Omit helper type 来完成操作:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
TypeScript 3.5 中,lib.d.ts 内置了一个 Omit type,并且可以在任何地方使用,开发者不再需要自己编写。
让每个人都定义自己的 Omit 版本,TypeScript 3.5将在lib.d.ts中包含它自己的版本,可以在任何地方使用。编译器本身将使用此 Omit type 来表示通过泛型上的对象 rest 析构声明创建的 type。
TypeScript 在对象中有一个称为多余属性检查的功能,此功能旨在检测 type 不符合特定属性时的问题。
type Style = {
alignment: string,
color?: string
};
const s: Style = {
alignment: "center",
colour: "grey"
// ^^^^^^ error!
};
在 TypeScript 3.4 及更早版本中允许某些多余的属性。如下,TypeScript 3.4 允许对象中的 name 属性不正确,即使它的 type 在 Point 和 Label 之间都不匹配。
type Point = {
x: number;
y: number;
};
type Label = {
name: string;
};
const thing: Point | Label = {
x: 0,
y: 0,
name: true // uh-oh!
};
因为不会对成员进行任何多余的属性检查,所以错误的 name 不会被在意,但在 TypeScript 3.5 中,现在 type 检查器至少会验证所有提供的属性是否属于某个联合成员并具有适当的类型,这意味着上面的示例将会抛出错误。
需要注意的是,只要属性 type 有效,仍允许部分重叠:
const pl: Point | Label = {
x: 0,
y: 0,
name: "origin" // okay
};
使用新的 --allowUmdGlobalAccess flag,现在可以像下边这样从任何地方,甚至模块里引用 UMD 全局声明:
export as namespace foo;
TypeScript 3.5 中将对泛型构造函数的推导操作整合了起来:
class Box<T> {
kind: "box";
value: T;
constructor(value: T) {
this.value = value;
}
}
class Bag<U> {
kind: "bag";
value: U;
constructor(value: U) {
this.value = value;
}
}
function composeCtor<T, U, V>(
F: new (x: T) => U, G: new (y: U) => V): (x: T) => V {
return x => new G(new F(x))
}
let f = composeCtor(Box, Bag); // has type '<T>(x: T) => Bag<Box<T>>'
let a = f(1024); // has type 'Bag<Box<number>>'
除了上面的组合模式之外,这种对泛型构造函数的新推导意味着在某些 UI 库(如 React)中对类组件进行操作的函数可以更正确地对泛型类组件进行操作。
type ComponentClass<P> = new (props: P) => Component<P>;
declare class Component<P> {
props: P;
constructor(props: P);
}
declare function myHoc<P>(C: ComponentClass<P>): ComponentClass<P>;
type NestedProps<T> = { foo: number, stuff: T };
declare class GenericComponent<T> extends Component<NestedProps<T>> {
}
// type is 'new <T>(props: NestedProps<T>) => Component<NestedProps<T>>'
const GenericComponent2 = myHoc(GenericComponent);
TypeScript 3.5 新增了一个功能 Smart Select,它为编辑器提供了一个 API,以基于语法的方式扩展文本选择,如下图所示,该功能可以更加智能地在编辑器中选择相应的语法结构代码。
此外,该功能是跨平台的,可供任何可以正确访问 TypeScript 语言服务器的编辑器使用。
此功能由中国开发者 Wenlu Wang(@Kingwl)贡献。
更多内容请查看「阅读原文」。