I am wondering what's the best way to achieve strongly typed static functions for Mongoose Schemas when using TypeScript.
I have a solution right now, but it feels messy and adds a lot of extra code if it has to be done for each schema. I will present it at the bottom of this post, but will show the current setup first:
I have the following interfaces:
interfaces/Player.ts
export interface Player {
name: string
password: string
}
export interface PlayerDocument extends Player, Document {
// statics
findByName(name: string): any
};
The reason I have two interfaces here is because I want to be able to use the Player interface without the Mongoose-bindings as well other places in the app. PlayerDocument here represent the schema-ready interface, which we will use here:
schemas/Player.ts
const playerSchema = new mongoose.Schema({
name: { type: String, required: true, unique: true },
password: String,
});
// Not using arrow functions because they prevent binding this.
// See mongoose-docs
playerSchema.statics.findByName = function(name: string) {
return this.find({ name: new RegExp(name, 'i') });
}
interface test {
findByName(name: string): any
}
export default mongoose.model<PlayerDocument>('Player', playerSchema);
The problem here, is that whenever I am now using the schema in other places of the app, I am not getting the static function findByName(name: string): any
present in the type.
app.ts
import PlayerSchema from './schemas/Player';
const test = async () => {
const x = await PlayerSchema.findByName('Erlend');
console.log(x);
}
This gives:
My solution, which seems hacky
I managed to solve the issue by creating the following combined type:
schemas/Player.ts
interface test {
findByName(name: string): any
}
type something = mongoose.Model<PlayerDocument> & test;
export default (mongoose.model<PlayerDocument>('Player', playerSchema)) as something;
Aand finally:
But as explained above, I feel like there should be a better way.. Ideas?