TypeScript で populate
Mongoose の TypeScript バインディングは、汎用パラメータ Paths
を populate()
に追加します。
import { Schema, model, Document, Types } from 'mongoose';
// `Parent` represents the object as it is stored in MongoDB
interface Parent {
child?: Types.ObjectId,
name?: string
}
const ParentModel = model<Parent>('Parent', new Schema({
child: { type: Schema.Types.ObjectId, ref: 'Child' },
name: String
}));
interface Child {
name: string;
}
const childSchema: Schema = new Schema({ name: String });
const ChildModel = model<Child>('Child', childSchema);
// Populate with `Paths` generic `{ child: Child }` to override `child` path
ParentModel.findOne({}).populate<{ child: Child }>('child').orFail().then(doc => {
// Works
const t: string = doc.child.name;
});
別の方法は PopulatedParent
インターフェイスを定義し、Pick<>
を使用して入力しているプロパティを取得することです。
import { Schema, model, Document, Types } from 'mongoose';
// `Parent` represents the object as it is stored in MongoDB
interface Parent {
child?: Types.ObjectId,
name?: string
}
interface Child {
name: string;
}
interface PopulatedParent {
child: Child | null;
}
const ParentModel = model<Parent>('Parent', new Schema({
child: { type: Schema.Types.ObjectId, ref: 'Child' },
name: String
}));
const childSchema: Schema = new Schema({ name: String });
const ChildModel = model<Child>('Child', childSchema);
// Populate with `Paths` generic `{ child: Child }` to override `child` path
ParentModel.findOne({}).populate<Pick<PopulatedParent, 'child'>>('child').orFail().then(doc => {
// Works
const t: string = doc.child.name;
});
PopulatedDoc
を使用
Mongoose はまた、ドキュメントインターフェイスの入力されたドキュメントを定義するのに役立つ PopulatedDoc
タイプをエクスポートします。
import { Schema, model, Document, PopulatedDoc } from 'mongoose';
// `child` is either an ObjectId or a populated document
interface Parent {
child?: PopulatedDoc<Document<ObjectId> & Child>,
name?: string
}
const ParentModel = model<Parent>('Parent', new Schema({
child: { type: 'ObjectId', ref: 'Child' },
name: String
}));
interface Child {
name?: string;
}
const childSchema: Schema = new Schema({ name: String });
const ChildModel = model<Child>('Child', childSchema);
ParentModel.findOne({}).populate('child').orFail().then((doc: Parent) => {
const child = doc.child;
if (child == null || child instanceof ObjectId) {
throw new Error('should be populated');
} else {
// Works
doc.child.name.trim();
}
});
ただし、PopulatedDoc
の代わりに最初のセクションからの .populate<{ child: Child }>
構文を使用することをお勧めします。理由は次のとおりです
child instanceof ObjectId
であるかどうかを確認するために、追加の確認を追加する必要があります。追加の確認が行われない場合、TypeScript コンパイラはProperty name does not exist on type ObjectId
でエラーになります。つまり、PopulatedDoc<>
を使用すると、doc.child
を使用するすべての場所で追加の確認が必要になります。Parent
インターフェイスでは、child
はハイドレートされたドキュメントです。そのため、lean()
またはtoObject()
を使用すると Mongoose がchild
のタイプを推測することが難しくなります。