说:已经有一个给定的架构定义对象:
const schema = {prop1:{type:String,maxLength:8},prop2 ...};
是否有可能:在不为每个架构对象声明接口的情况下,创建一个相应的类,该类可以生成具有从架构中提取的prop1:String,prop2 ...的文档。
我希望我的应用中有类似的内容:
// schema definition:
const PersonSchema = { name: { type: String, maxLength: 8 } };
// class factory
const PersonClass = SchemaClassFactory(PersonSchema);
// instance with props defined in schema.
let person1 = new PersonClass();
person1.name = 'Jack';
let person2 = new PersonClass();
person2.name = 3; // should be wrong hinted by tslint.
我该如何实现?
答案 0 :(得分:2)
您可以使用映射类型和条件类型为模式对象创建一个类,以从模式中提取对象的形状。
下面是一个可能的解决方案,我不确定我是否涵盖了用mongoose定义架构的所有方法,但这应该会让您注目:
const PersonSchema = {
name: { type: String, maxLength: 8 },
age: { type: Number },
title: String,
id: ObjectID
};
type PrimitiveConstructor<T> = {
new (...a: any[]): any;
(...a: any[]): T
}
type Constructor<T> = {
new (...a: any[]): T;
}
type ExtractType<T> = {
[P in keyof T] :
T[P] extends PrimitiveConstructor<infer U>? U :
T[P] extends { type: PrimitiveConstructor<infer U> } ? U:
T[P] extends Constructor<infer U> ? U :
T[P] extends { type: Constructor<infer U> } ? U:
never
}
function createClass<T>(schema: T): new (data?: Partial<ExtractType<T>>) => ExtractType<T> {
// The class will not have the fields explicitly defined since we don't know them but that is fine
return new class {
// Optional constructor for assigning data to the fields, you can remove this if not needed
constructor(data?: any){
if(data) {
Object.assign(this, data);
}
}
} as any;
}
var PersonClass = createClass(PersonSchema);
type PersonClass = InstanceType<typeof PersonClass>
let p = new PersonClass();
p.name ="";
p.name = 2; // error
p.id = new ObjectID(10);
let p2 = new PersonClass({
name: "",
});