node.js - ฉันจะเพิ่มเมธอดสแตติกให้กับโมเดล Mongoose ใน Typescript สำหรับ Mongoose 5.11 ได้อย่างไร?
ใน Mongoose 5.10 ฉันใช้รูปแบบต่อไปนี้ในการเพิ่มเมธอดสแตติกให้กับโมเดล Mongoose ของฉัน:
import { Schema, Document, Model, Connection } from "mongoose";
import { v4 } from "uuid";
export interface IFoo extends Document {
id: string;
name: string;
}
export interface IFooModel extends Model<IFoo> {
findOneOrCreate({ name }: { name: string }): Promise<IFoo>;
}
const fooSchema = new Schema({
id: {
type: String,
required: true,
default: () => `a-${v4()}`,
},
name: {
type: String,
required: true,
unique: true,
},
});
fooSchema.static({
findOneOrCreate: async function (
this: IFooModel,
{ name }: { name: string }
): Promise<IFoo> {
let foo = await this.findOne({ name });
if (!foo) {
foo = await this.create({ name });
}
return foo;
},
});
export default function (db: Connection): IFooModel {
return db.model<IFoo, IFooModel>("Foo", fooSchema);
}
ใน Mongoose 5.11, Mongoose รวมการกำหนดประเภทของ Typescript ของตัวเอง; ซึ่งแทนที่สิ่งที่ถูกกำหนดใน @types/mongoose การอัปเดตเหล่านี้ลบพารามิเตอร์ประเภทที่สองออกจาก mongoose.model() และส่งผลให้เกิดข้อผิดพลาดประเภทดังต่อไปนี้:
src/models/foo.ts:40:3 - error TS2741: Property 'findOneOrCreate' is missing in type 'Model<IFoo>' but required in type 'IFooModel'.
40 return db.model<IFoo, IFooModel>("Foo", fooSchema);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/models/foo.ts:10:3
10 findOneOrCreate({ name }: { name: string }): Promise<IFoo>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'findOneOrCreate' is declared here.
src/models/foo.ts:40:19 - error TS2558: Expected 1 type arguments, but got 2.
40 return db.model<IFoo, IFooModel>("Foo", fooSchema);
~~~~~~~~~~~~~~~
Found 2 errors.
ด้วยการกำหนดประเภทใหม่ของ Mongoose 5.11 วิธีที่ถูกต้องในการเพิ่มเมธอดสแตติกเหล่านี้ให้กับโมเดลของฉันคืออะไร?
คำตอบ #1
กุญแจสำคัญคือการตั้งค่าประเภททั่วไปในตัวสร้าง Schema แบบนี้:
const fooSchema = new Schema<IFoo, IFooModel>({
id: {
type: String,
required: true,
default: () => `a-${v4()}`,
},
name: {
type: String,
required: true,
unique: true,
},
});
ฉันก็มีปัญหาเล็กน้อยกับประเภทเอกสารที่ไม่ตรงกับประเภทโมเดลที่ส่งกลับ ดังนั้นฉันจึงขอแนะนำให้สร้างชนิดยูเนียนใหม่แบบนี้ แล้วจึงใช้ชนิดที่คุณต้องการตามลำดับ:
export interface IFoo {
id: string;
name: string;
}
type IFooDocument = IFoo & Document;
