我想创建一个将实际类对象本身作为参数的函数(实际上是在充满多个参数的对象中),并且我希望将函数的返回类型推断为该类的实例,该实例是作为参数提供。
这是一个ORM,因此这些类是模型,每个模型都代表一个SQL表。然后将有许多数据库查询功能(在类之外),每个功能都带有指示从中选择哪个表的参数。
最好用代码解释...
export class DogModelClass {
id:number;
name:string;
woofCount:number;
}
export class CatModelClass {
id:number;
name:string;
meowCount:number;
}
interface ArgumentsInterface {
theActualClass; // <-- this argument will be the actual CLASS itself, NOT instance of the class
}
function getModelFromDatabase(args:ArgumentsInterface) {
// some database code to get the a "dog" or "cat" row from the DB and return an INSTANCE of the relevant args.theActualClass class
}
// I want typescript to infer that dogInstance is an INSTANCE of DogModelClass (simply from the function arguments alone)...
const dogInstance = getModelFromDatabase({theActualClass:DogModelClass});
// I want typescript to infer that catInstance is an INSTANCE of CatModelClass (simply from the function arguments alone)...
const catInstance = getModelFromDatabase({theActualClass:CatModelClass});
我知道我可以在函数本身中添加泛型,即
function getModelFromDatabaseWithGeneric<ModelGeneric>(args:ArgumentsInterface):ModelGeneric {
return <ModelGeneric>{};
}
const dogInstance2 = getModelFromDatabaseWithGeneric<DogModelClass>({theActualClass:DogModelClass});
但是我不想每次调用函数时都必须设置泛型类型,因为出于其他原因(例如,函数知道要选择哪个表,无论如何,都必须在参数中设置模型类本身)从等)。因此,每次调用所有查询函数时都必须两次写入类名称是一种冗余。
我该如何实现?
也请让我知道我是否可以使用所有更准确的术语。当将它们作为这样的变量传递时,我从不十分确定在JS中如何称呼“实际的类对象-而不是实例”。
InstanceType
的方式来实现:function getModelFromDatabase<T extends { new(...args: any[]): any }>(args: { theActualClass: T }): InstanceType<T> { /* ... */ }
或者,如果愿意,可以确保参数始终是构造函数类型:
function getModelFromDatabase<T>(args: { theActualClass: {new (...args: any[]): T} }): T { /* ... */ }
两者都实现了相同的目标:
// Infered as an INSTANCE of DogModelClass const dogInstance = getModelFromDatabase({theActualClass: DogModelClass}); // Infered as an INSTANCE of CatModelClass const catInstance = getModelFromDatabase({theActualClass: CatModelClass});