【发布时间】:2022-01-18 03:20:04
【问题描述】:
所以我有一个很大的网络应用程序。这解决了很多实体。 例如:
enum EntityTypes {
EntityA = 'A',
EntityB = 'B',
EntityC = 'C',
EntityD = 'D',
}
interface EntityA {
type: EntityTypes.EntityA;
aSpecialProperty: boolean;
}
interface EntityB {
type: EntityTypes.EntityB;
bSpecialProperty: boolean;
}
interface EntityC {
type: EntityTypes.EntityC;
cSpecialProperty: string;
}
interface EnityD {
type: EntityTypes.EntityD;
dSpecialProperty: number;
}
我们这样做是因为我们稍后希望像这样解析每种类型独有的属性(到目前为止,我们都是这样做的):
type EntityTypesResolver<T extends EntityTypes> = T extends EntityTypes.EntityA
? EntityA
: T extends EntityTypes.EntityB
? EntityB
: T extends EntityTypes.EntityC
? EntityC
: T extends EntityTypes.EntityD
? EntityD
: never;
type EntityResolver<ResultType> = {
[P in EntityTypes]: (entity: EntityTypesResolver<P>) => ResultType;
};
const resolver: EntityResolver<string> = {
[EntityTypes.EntityA]: (entity) => `${entity.aSpecialProperty}`,
[EntityTypes.EntityB]: (entity) => `${entity.bSpecialProperty}`,
[EntityTypes.EntityC]: (entity) => entity.cSpecialProperty,
[EntityTypes.EntityD]: (entity) => `${entity.dSpecialProperty}`,
};
问题:我想消除(或找到更优雅的解决方案)EntityTypesResolver,因为它看起来像一个容易出错的代码块,原因如下:
- 由于我们是一个致力于此代码库的大型团队,我不想依赖其他程序员记住维护这种类型
- 这里的可读性很糟糕
我很长时间都试图为此找到一个优雅的解决方案,但似乎没有取得任何成果。
@jcalz提出的解决方案:
我对这个解决方案的问题是我仍然必须依靠其他程序员来维护Entity 类型别名。
//这两行
type Entity = EntityA | EntityB | EntityC | EntityD
type EntityTypesResolver<T extends EntityTypes> = Extract<Entity, { type: T }>
【问题讨论】:
-
this approach 是否满足您的需求?您维护一个像
type Entity = EntityA | EntityB | EntityC | EntityD这样的工会,您可以在需要时向其中添加新的工会成员。如果这对你有用,我可以写一个答案;如果没有,请edit您的问题以显示不满意的用例。 -
@jcalz ,按要求编辑了帖子
-
TypeScript 无法自行“发现”您的实体接口(无法迭代已知接口,而且您甚至不希望有人可以在某处添加新的
interface Whoopsie {type: EntityTypes.EntityB, randomThing: string}并破坏您的代码; 你需要告诉它它们是哪些。像type Entity = EntityA | EntityB | EntityC | EntityD这样的东西可能是最轻量级的方法(特别是与你的原始版本相比)。如果你愿意进行重大重构,比如this,你可以它更自动。 -
如果最后的重构对你有用,那么我可以写出来。如果没有,并且您需要在范围内手动创建接口
EntityA、EntityB,那么您还必须手动将它们放入包中以供编译器查找。让我知道您想看到哪种答案。在最坏的情况下,我只会回答我最初的建议,这是对您当前代码的改进,以及为什么它不能变得更好的警告。 -
@jcalz 有什么办法可以强制执行 EntityTypeResolver 以便通过的联合将包含所有枚举键?
标签: typescript typescript-generics