当一个类型是映射的任何成员时,提高Typescript的速度



例如,我有以下类型:

class User extends Entity {}
class Post extends Entity {}
type Entities = {
user: User,
post: Post,
// potentially hundreds more
};
type EntityType = 'user' | 'post' | ...;

当我在泛型中使用EntitiesEntityType时,它明显减慢了Typescript的速度。仅在VS代码中显示类型信息就需要几分钟的时间。我有一些通用功能,比如:

function getEntityFromCache<T extends EntityType>(type: T, id: number): Entities[T] | null | undefined;
function getEntity<T extends EntityType>(type: T, id: number): Entities[T] | null {
const cachedEntity = getEntityFromCache(type, id);
if (cachedEntity !== undefined) {
return cachedEntity;
}
...
}

我之所以理解这是缓慢的,是因为Entities[T]Entities的所有值的并集,即User | Post | ...。TS不能很好地处理工会。为了检查cached的返回类型是否正确,TS必须遍历T的每个可能值。即如果是T = 'user',则验证cachedEntityEntities['user'];如果是T = 'post',则验证cachedEntityEntities['post'];等等。这很慢,因为每次我有泛型时,TS都必须检查并集的每个值。

此外,TS不只是比较泛型值('user' === 'user''post' === 'post'),而是比较整个实体(User === UserPost === Post)。这使情况变得更糟,因为实体很复杂。

有什么方法可以加快速度?以下是我的一些想法:

  1. 从中间函数中删除泛型,使它们返回基本实体类型,然后进行类型转换。例如function getEntityFromCache(type: T, id: number): Entity | null | undefined;

  2. 以某种方式使TS比较实体类型字符串,而不是比较整个实体。

根据TypeScript wiki页面"偏好基类型而非并集"值得使用子类型,而不是联合。

然而,它们也有成本。每次将参数传递给printSchedule时,都必须将其与并集的每个元素进行比较。对于两个元素的并集来说,这是琐碎而廉价的。但是,如果您的并集有十几个元素,则可能会在编译速度方面造成实际问题。例如,为了从并集中消除冗余成员,必须成对比较元素,这是二次的。这种检查可能发生在与大型并集相交时,其中与每个并集成员相交可能会导致需要减少的大量类型。避免这种情况的一种方法是使用子类型,而不是联合。

文档中的简化示例:


interface A {
char: 'a' | 'b' | 'c' | 'd' | 'e';
}
interface B extends A {
char: 'a' | 'b';
}
interface C extends A {
char: 'd' | 'e';
}

declare function char(schedule: A): void;

相关内容

  • 没有找到相关文章

最新更新