I am currently working on a library and facing difficulties with dynamically inferring types.
Within the library, the useModel
function returns a Model instance.
class Database {
...
public useModel(target: Function) {
const tableName = getClassMetadata(target).name;
const table = this.config.tables.find(({ name }) => name === tableName);
// The issue lies here - type is not being inferred
type RType = typeof target extends (...args: any[]) => infer RT ? RT : Function;
// Model has selectAll() which returns RType[]
return new Model<RType>(this.connection, table);
}
}
Below is an example of how the library would be used by a consumer.
Custom decorators are used to add metadata values.
@Table({ name: 'Users', timestamps: true })
class Users {
@PrimaryKey({autoIncrement: true, unique: true,})
id: number;
@Indexed({ unique: true })
@Default('John')
username: string;
@Default(0)
@Indexed({ unique: false })
age: number;
}
const database = new Database({
version: 1,
name: 'MyDatabase',
tables: [Users],
});
// The goal is for the Users class to be automatically inferred in useModel
const usersModel = database.useModel(Users);
usersModel.selectAll().then((users) => {
users?.forEach((user) => {
// user is not being inferred here :(
console.log(user);
});
});
Using generics in useModel
would solve the issue, but the desire is to avoid explicit generic values like
const usersModel = database.useModel<typeof Users>(Users);
The objective is for the Users class to be inferred automatically when using useModel
This is the expected usage
const usersModel = database.useModel(Users);
Any suggestions to achieve this?