TypeScript:当提供变量 CLASS 作为函数参数时,将返回类型推断为该类的实例(仅来自参数)
Posted
技术标签:
【中文标题】TypeScript:当提供变量 CLASS 作为函数参数时,将返回类型推断为该类的实例(仅来自参数)【英文标题】:TypeScript: when supplying a variable CLASS as a function argument, infer the return type to be an instance of that class (purely from argument alone) 【发布时间】:2020-06-06 16:10:37 【问题描述】:我想创建一个将实际类对象本身作为参数的函数(实际上是在一个充满多个参数的对象中),并且我希望将函数的返回类型推断为该类的实例作为参数提供。
这是一个 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 中如何调用“实际的类对象 - 而不是实例”。
【问题讨论】:
【参考方案1】:实现这一点的一种方法是将泛型类型限制为类构造函数,然后返回其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);
【讨论】:
谢谢你,对我很有用!两者都非常适合我正在尝试做的事情。后续问题:我只是好奇为什么它包含any[]
...方括号暗示某处涉及到一个数组,但我想不出数组是如何相关的?
any[]
是构造函数类型签名的一部分,代表它的参数。由于带参数的类构造函数不能分配给不带参数的构造函数,因此我们允许使用 ...args: any[]
语法的任意数量的任意参数。如果你不喜欢any
,那么在它的位置使用unknown
可以获得相同的结果。详情请见here。以上是关于TypeScript:当提供变量 CLASS 作为函数参数时,将返回类型推断为该类的实例(仅来自参数)的主要内容,如果未能解决你的问题,请参考以下文章
vue-class-component + typescript:如何在导入的函数中使用组件的类作为“this”的类型?
应由服务提供的 Typescript Angular 访问参数
Typescript:环境变量的类型 Guard 作为 JSON 对象的键