首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型记录:构造函数的散列

类型记录:构造函数的散列
EN

Stack Overflow用户
提问于 2017-08-10 19:48:52
回答 1查看 404关注 0票数 1

我有一个表示数据模型的抽象类。我们叫它模特吧。它实际上是在ModelData类型中参数化的,它表示模型实际拥有的数据类型。所以:

代码语言:javascript
复制
export interface ModelData { type: string; attributes: {} }
export class Model<D extends ModelData> {}
export interface UserData extends ModelData 
  { type: 'users', attributes: { name: string; }}
export class Users extends Model<UserData> {}

问题是,我希望保留一个模型构造函数的存储库。当我的数据存储给我一个类似于:{ type: 'users', id: 1 }的引用列表时,我喜欢做refs.map(v => new ctors[v.type]({id: v.id}))之类的事情。

问题是,我不知道如何声明“此对象包含字符串索引的子类构造函数集。

我以前做过

代码语言:javascript
复制
private types: { [type: string]: typeof Model }

然后

代码语言:javascript
复制
find<T extends ModelData>(ref: ModelReference): Model<T> {
  return new types[ref.type]({id: ref.id})
}

或多或少(为了简洁起见,省略了额外的空守卫和其他代码)。

这实际上是不正确的--我实际上返回的是extends Model<T>,而我在类型中存储的不是typeof Model,而是extends typeof Model

在2.4.1之前(我认为这与隐含的泛型更改有关)编译的代码没有抱怨,尽管不正确。我很高兴把它做对了,但我不知道我怎么能用打字本来表达这个问题。

我得到的具体内容是一组ModelData类型,它为ModelData的属性和关系属性定义了不同的形状,以及一组扩展了这些ModelData类型的模型的类。因此,虽然从技术上讲,我可以返回一个模型,但我宁愿返回一个用户,因为我可能会给用户添加一些额外的方便方法。

那么,是否有可能说,“这个东西包含一个字符串索引的构造函数组,而所有这些构造函数都遵循”扩展AbstractClass“的模式?

EN

回答 1

Stack Overflow用户

发布于 2017-08-10 20:48:07

我建议你这样做:

代码语言:javascript
复制
const types = {
  'users': Users,
  // ... other Models
}

function find<K extends keyof typeof types>(ref: { type: K }): typeof types[K]['prototype'] {
  return new types[ref.type](); // this only works if all Models have no-arg constructors
}

如果您需要验证types是否正确,有一种方法可以使用new关键字引用某事物的构造函数:

代码语言:javascript
复制
type Constructor<T> = {
  new(...args: any[]): T;
  readonly prototype: T;
}

如果我想说“此对象的值是适当的Model类型的构造函数,其中键与ModelData['type']值相同”,我想说:

代码语言:javascript
复制
type ModelMap<T> = {
  [K in keyof T]: Constructor<Model<ModelData & { type: K }>>
}
function verifyTypes<T>(types: T, alsoTypes: ModelMap<T>) { }
verifyTypes(types, types);

如果verifyTypes()给出了一个编译器错误,那是因为其中一个值是错误的:

代码语言:javascript
复制
const types = {
   'user': Users
}
verifyTypes(types, types); // error: type of property 'user' is incompatible

请注意,只有当您的Model类型实际保留正确的ModelData类型的某些属性时,编译器才会生气。如示例所示,如果它们是空的,那么所有类型在结构上都是相同的,编译器也不会抱怨:

代码语言:javascript
复制
export class Model<D extends ModelData> { 
  data: D; // that's enough 
}

希望这能有所帮助。祝好运!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45622374

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档