TypeScript:当提供变量CLASS作为函数参数时,推断返回类型为该类的实例(仅从参数中得出)

问题描述 投票:0回答:1

我想创建一个将实际类对象本身作为参数的函数(实际上是在充满多个参数的对象中),并且我希望将函数的返回类型推断为该类的实例,该实例是作为参数提供。

这是一个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中如何称呼“实际的类对象-而不是实例”。

typescript class generics types type-inference
1个回答
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});

© www.soinside.com 2019 - 2024. All rights reserved.