使用节点和猫鼬实现接口的正确方法是什么?
What is the correct way to implement interfaces with node and mongoose?
我为我的模型创建了一个界面,我只想return记录中的特定数据
// code.interface.ts
import { Document } from 'mongoose';
export interface CodeI extends Document {
readonly _id: string;
readonly logs: any;
}
但是当我从 mongo 得到结果时,它完全忽略了我界面中的内容。 (我正在使用 NestJs 作为框架)
//constructor
constructor(@InjectModel(Coupon.name) private couponModel: Model<CouponDocument>) {}
// function
async findOne(codeId: string): Promise<CodeI> {
const coupon = await this.couponModel.findOne({ _id: codeId }).exec();
if (!coupon) {
throw new NotFoundException([`#${codeId} not found`]);
}
return coupon;
}
TypeScript 接口不是这样工作的。它们不能限制对象的字段,因为它们在运行时不存在,所以,我们不能用它们来指导任何运行时行为。 TypeScript 接口仅对编译时类型检查有用。
但是,对于您的情况,有两种方法可以实现预期的行为。
- 第一个是 select 仅 return 需要的必填字段(推荐)。
在你的 findOne 中,你可以做这样的事情
async findOne(codeId: string): Promise<CodeI> {
const coupon = await this.couponModel.findOne({ _id: codeId }, '_id logs').exec();
if (!coupon) {
throw new NotFoundException([`#${codeId} not found`]);
}
return coupon;
}
在这里,如您所见,我向 findOne 函数传递了一个额外的字符串类型参数,它是投影,它将 select 仅从对象中指定的字段。这不仅可以解决您的问题,还可以节省查询时间并提高查询性能。 Read more about findOne here.
- 另一种方法是创建一个 DTO,您可以在其中定义要从函数中 return 的字段。
像这样:
// CouponDto.ts
class CouponDto {
public readonly _id: string;
public readonly logs: any;
constructor(data: CodeI) {
this._id = data._id;
this.logs = data.logs;
}
}
然后,在您的服务文件中,您可以执行类似
的操作
return new CouponDto(coupon);
(确保将函数的 return 类型也更改为 CouponDto
)
您可以使用这两种方式中的任何一种。虽然我建议使用第一个,但这取决于您以及您想要如何构建项目。
外部链接:
我为我的模型创建了一个界面,我只想return记录中的特定数据
// code.interface.ts
import { Document } from 'mongoose';
export interface CodeI extends Document {
readonly _id: string;
readonly logs: any;
}
但是当我从 mongo 得到结果时,它完全忽略了我界面中的内容。 (我正在使用 NestJs 作为框架)
//constructor
constructor(@InjectModel(Coupon.name) private couponModel: Model<CouponDocument>) {}
// function
async findOne(codeId: string): Promise<CodeI> {
const coupon = await this.couponModel.findOne({ _id: codeId }).exec();
if (!coupon) {
throw new NotFoundException([`#${codeId} not found`]);
}
return coupon;
}
TypeScript 接口不是这样工作的。它们不能限制对象的字段,因为它们在运行时不存在,所以,我们不能用它们来指导任何运行时行为。 TypeScript 接口仅对编译时类型检查有用。
但是,对于您的情况,有两种方法可以实现预期的行为。
- 第一个是 select 仅 return 需要的必填字段(推荐)。
在你的 findOne 中,你可以做这样的事情
async findOne(codeId: string): Promise<CodeI> {
const coupon = await this.couponModel.findOne({ _id: codeId }, '_id logs').exec();
if (!coupon) {
throw new NotFoundException([`#${codeId} not found`]);
}
return coupon;
}
在这里,如您所见,我向 findOne 函数传递了一个额外的字符串类型参数,它是投影,它将 select 仅从对象中指定的字段。这不仅可以解决您的问题,还可以节省查询时间并提高查询性能。 Read more about findOne here.
- 另一种方法是创建一个 DTO,您可以在其中定义要从函数中 return 的字段。 像这样:
// CouponDto.ts
class CouponDto {
public readonly _id: string;
public readonly logs: any;
constructor(data: CodeI) {
this._id = data._id;
this.logs = data.logs;
}
}
然后,在您的服务文件中,您可以执行类似
的操作return new CouponDto(coupon);
(确保将函数的 return 类型也更改为 CouponDto
)
您可以使用这两种方式中的任何一种。虽然我建议使用第一个,但这取决于您以及您想要如何构建项目。
外部链接: