打字稿:构造函数的哈希

时间:2017-08-10 19:48:52

标签: typescript

我有一个表示数据模型的抽象类。我们称之为模型。它实际上是在ModelData类型中参数化的,它表示模型实际具有的数据类型。所以:

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}))或类似的东西。

问题在于我不知道如何声明&#34;该对象包含一组字符串索引的子类构造函数。

我曾经做过

private types: { [type: string]: typeof Model }

然后

find<T extends ModelData>(ref: ModelReference): Model<T> {
  return new types[ref.type]({id: ref.id})
}

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

这实际上并不正确 - 我实际返回的内容是extends Model<T>,而我在类型中存储的内容不是typeof Model,而是{{ 1}}。

在2.4.1之前(我假设这与隐式通用更改有关)代码编译时没有抱怨,尽管不正确。我很高兴使正确,但我不确定如何使用打字稿来表达这一点。

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

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

1 个答案:

答案 0 :(得分:1)

我建议做类似的事情:

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关键字引用某个构造函数:

type Constructor<T> = {
  new(...args: any[]): T;
  readonly prototype: T;
}

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

type ModelMap<T> = {
  [K in keyof T]: Constructor<Model<ModelData & { type: K }>>
}
function verifyTypes<T>(types: T, alsoTypes: ModelMap<T>) { }
verifyTypes(types, types);

如果verifyTypes()给你编译错误,那是因为其中一个值不好:

const types = {
   'user': Users
}
verifyTypes(types, types); // error: type of property 'user' is incompatible

请注意,如果您的Model类型实际上保留了右ModelData类型的某些属性,编译器就会生气。如果它们是空的,如您的示例所示,您的所有类型将在结构上相同,编译器将永远不会抱怨:

export class Model<D extends ModelData> { 
  data: D; // that's enough 
}

希望有所帮助。祝你好运!