TypeScript性能优化(一)编写易于编译的代码

在类型组合时选择 interface

大多数情况下,一个简单的 type
interface
是非常相似的

interface Foo {
prop: string
}

type Bar = {
prop: string
};

但是,一旦你需要组合两个或多个类型,推荐选择使用 interface
扩展这些类型,或者使用 type
组合这些类型,这种情况就有区别了。

interface
创建一个单一的平面对象类型来检测属性冲突,另一方面,和其他类型的扩展只是递归地归并属性,在某些情况下会产生 never
interface
的一致性也更好。而组合的 type alias
不能在其他交集的部分中显示。 interface
之间的类型关系也会被缓存,而不是作为一个整体的组合类型。
不推荐的:

type Foo = Bar & Baz & {
someProp: string;
}

推荐写法:

interface Foo extends Bar, Baz {
someProp: string;
}

使用类型注释

推荐添加类型注释,特别是返回指的类型,这可以为编译器节省大量工作。在某种程度上,这是因为命名类型往往比匿名类型更紧凑(编译器可能会更容易推断出匿名类型),这减少了花费在读取和写入声明文件上的时间(例如用于增量构建)。类型推断是非常方便的,所以没有必要普遍地这样做,但是,如果您已经确定了代码构建缓慢的部分,那么还是值得一试的。
不推荐的:

import {
otherFunc
} from "other";

export function func() {}

推荐写法:

import {
otherFunc,
otherType
} from "other";

export function func(): otherType {
return otherFunc();
}

优先使用基本类型而不是联合类型

联合类型非常好用–它可以让你表达一种类型的可能值范围

interface WeekdaySchedule {
day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday";
wake: Time;
startWork: Time;
endWork: Time;
sleep: Time;
}

interface WeekendSchedule {
day: "Saturday" | "Sunday";
wake: Time;
familyMeal: Time;
sleep: Time;
}

declare function printSchedule(schedule: WeekdaySchedule | WeekendSchedule);

但是联合类型也带来了一定开销。每次将参数传递给 printSchedule
时,都需要比较 WeekdaySchedule
WeekendSchedule
里的每个元素。对于一个由两个元素组成的联合类型来说,这是微不足道的。但是,如果你的联合类型有很多元素,这将引起编译速度的问题。
当大量联合类型交叉一起时发生这种检查,会在每个联合类型上相交导致大量的类型,需要减少这种情况发生。避免这种情况的一种方法是使用子类型,而不是联合类型。

interface Schedule {
day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday";
wake: Time;
sleep: Time;
}

interface WeekdaySchedule extends Schedule {
day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday";
startWork: Time;
endWork: Time;
}

interface WeekendSchedule extends Schedule {
day: "Saturday" | "Sunday";
familyMeal: Time;
}

declare function printSchedule(schedule: Schedule);

举一个更明显的例子:假如你在定义每种内置 DOM
元素的类型。这种情况下,更优雅的方式是创建一个包含所有元素的 HtmlElement
基础类型,其中包括 DivElement
ImgElement
等。然后推荐使用继承而不是创建一个无穷多的联合类型 DivElement | /.../ | ImgElement | /.../

项目引用

使用 TypeScript
构建一个比较庞大的项目时,将代码库组织成几个独立的项目会很有用。每个项目都有自己的 tsconfig.json
,可能它会对其他项目有依赖性。这有益于避免在一次编译中导入太多文件,也使某些代码库布局策略更容易地放在一起。

有一些非常基本的方法将一个代码库分解成多个项目。例如:将 Server
Client
端拆分开。

              ------------
| |
| Shared |
^----------^
/ \
/ \
------------ ------------
| | | |
| Client | | Server |
-----^------ ------^-----

本系列译自 TypeScript 官方 wiki