假设我有两个模式:
Foo.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface IFoo extends Document {
name: string;
}
const fooSchema = new Schema(
{
name: {
type: String,
required: true,
}
}
);
export default mongoose.model<IFoo>('Foo', fooSchema);
和Bar.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface IBar extends Document {
fooId: string | IFoo; // can be string or can be Foo document
}
const barSchema = new Schema(
{
fooId: {
type: Schema.Types.ObjectId,
ref: 'Foo',
required: true,
},
title: String;
}
);
export default mongoose.model<IBar>('Bar', barSchema);
现在,当我找到一个填充了Foo
的Bar
文档时。我从打字中得到一个编译错误
const bar = await Bar.findOne({ title: 'hello' }).populate({ path: 'fooId', model: 'Foo' });
bar.fooId.name // here typescript gives an error
错误为
类型"string"上不存在属性"name">
由于我在IBar
中定义了fooId
可以是string | IFoo
。打字为什么抱怨?如何解决?
如果您检查populate
方法的类型,您可以看到它的结果类型只是this
。因此,在寻址fooId
属性的name
字段之前,必须将结果的类型显式缩小为IFoo
类型:
const bar = await Bar.findOne({ title: 'hello' })
.populate({ path: 'fooId', model: 'Foo' });
if (typeof bar.fooId !== 'string') { // discards the `string` type
bar.fooId.name
}
或者只需键入断言结果:
const bar = await Bar.findOne({ title: 'hello' })
.populate({ path: 'fooId', model: 'Foo' });
(bar.fooId as IFoo).name