I am trying to use Mongoose together with TypeScript.
With JavaScript alone, we can pretty easily write the schema for a model Foo
.
const fooSchema = new mongoose.Schema({
name: String,
value: Number
});
fooSchema.methods.someInstanceMethod = function() {/*...*/};
fooSchema.statics.someStaticMethod = function() {/*...*/};
const Foo = mongoose.model('Foo', fooSchema);
And we can use Foo
like so:
Foo.someStaticMethod();
var foo = new Foo();
foo.someInstanceMethod();
foo.name;
-
However, now that we have TypeScript, we will get error messages:
Property 'someStaticMethod' does not exist on type 'Model'.
Property 'someInstanceMethod' does not exist on type 'Document'.
Property 'name' does not exist on type 'Document'.
After some research, I gathered that the way to fix this is to declare the following interfaces:
export interface IFooDocument extends mongoose.Document {
name: string;
value: number;
someInstanceMethod(): any;
}
export interface IFooModel extends mongoose.Model<IFooDocument> {
someStaticMethod(): any;
}
And adjust Foo
to be:
export const Foo = <IFooModel>mongoose.model<IFooDocument>('Foo', fooSchema);
-
The issue I have with this approach is that we essentially need to rewrite the Schema twice - once on fooSchema
, and once on the interfaces. To me, the necessity of having to make sure the interface and schema are always kept in sync introduces just as many problems as type checking solves.
So my question is: Is there a way to avoid having to rewrite the Schema twice and still use types? Is there a better way to keep the schema and interface in sync?
Or alternatively, perhaps Mongoose is not the right ODM solution if I am using TypeScript? Is there a better solution?