我最近一直在研究 NestJS 并开始了一些示例项目。这个项目使用 MongoDB,所以我也选择了 Typegoose 来实现这一点。我在网上找到了一个教程(https://nartc.netlify.app/blogs/nestjs-typegoose/),它描述了如何将一些抽象与基本类型鹅模型一起使用。
所以,我base.service.ts
现在看起来像这样:
import { InternalServerErrorException } from '@nestjs/common';
import { DocumentType, ReturnModelType } from '@typegoose/typegoose';
import { AnyParamConstructor } from '@typegoose/typegoose/lib/types';
import { MongoError } from 'mongodb';
import { DocumentQuery, Types, Query, UpdateQuery } from 'mongoose';
import { BaseModel } from './base.model';
type QueryList<T extends BaseModel> = DocumentQuery<
Array<DocumentType<T>>,
DocumentType<T>
>;
type QueryItem<T extends BaseModel> = DocumentQuery<
DocumentType<T>,
DocumentType<T>
>;
export abstract class BaseService<T extends BaseModel> {
protected model: ReturnModelType<AnyParamConstructor<T>>;
protected constructor(model: ReturnModelType<AnyParamConstructor<T>>) {
this.model = model;
}
protected static throwMongoError(err: MongoError): void {
throw new InternalServerErrorException(err, err.errmsg);
}
protected static toObjectId(id: string): Types.ObjectId {
try {
return Types.ObjectId(id);
} catch (e) {
this.throwMongoError(e);
}
}
createModel(doc?: Partial<T>): T {
return new this.model(doc);
}
findAll(filter = {}): QueryList<T> {
return this.model.find(filter);
}
async findAllAsync(filter = {}): Promise<Array<DocumentType<T>>> {
try {
return await this.findAll(filter).exec();
} catch (e) {
BaseService.throwMongoError(e);
}
}
findOne(filter = {}): QueryItem<T> {
return this.model.findOne(filter);
}
async findOneAsync(filter = {}): Promise<DocumentType<T>> {
try {
return await this.findOne(filter).exec();
} catch (e) {
BaseService.throwMongoError(e);
}
}
findById(id: string): QueryItem<T> {
return this.model.findById(BaseService.toObjectId(id));
}
async findByIdAsync(id: string): Promise<DocumentType<T>> {
try {
return await this.findById(id).exec();
} catch (e) {
BaseService.throwMongoError(e);
}
}
async create(item: T): Promise<DocumentType<T>> {
try {
return await this.model.create(item);
} catch (e) {
BaseService.throwMongoError(e);
}
}
delete(filter = {}): QueryItem<T> {
return this.model.findOneAndDelete(filter);
}
async deleteAsync(filter = {}): Promise<DocumentType<T>> {
try {
return await this.delete(filter).exec();
} catch (e) {
BaseService.throwMongoError(e);
}
}
deleteById(id: string): QueryItem<T> {
return this.model.findByIdAndDelete(BaseService.toObjectId(id));
}
async deleteByIdAsync(id: string): Promise<DocumentType<T>> {
try {
return await this.deleteById(id).exec();
} catch (e) {
BaseService.throwMongoError(e);
}
}
update(item: T): QueryItem<T> {
return this.model.findByIdAndUpdate(BaseService.toObjectId(item.id), item, {
new: true
});
}
async updateAsync(item: T): Promise<DocumentType<T>> {
try {
return await this.update(item).exec();
} catch (e) {
BaseService.throwMongoError(e);
}
}
count(filter = {}): Query<number> {
return this.model.count(filter);
}
async countAsync(filter = {}): Promise<number> {
try {
return await this.count(filter);
} catch (e) {
BaseService.throwMongoError(e);
}
}
}
这与上述博客文章中的代码完全相同。但是,我遇到了一些错误:
No overload matches this call.
The last overload gave the following error.
Argument of type 'T' is not assignable to parameter of type 'UpdateQuery<DocumentType<T>>'.
Type 'BaseModel' is not assignable to type 'UpdateQuery<DocumentType<T>>'.
Type 'BaseModel' is not assignable to type '_UpdateQuery<_AllowStringsForIds<LeanDocument<DocumentType<T>>>> & ReadonlyPartial<_AllowStringsForIds<LeanDocument<DocumentType<T>>>> & DotAndArrayNotation<...>'.
Type 'BaseModel' is not assignable to type 'ReadonlyPartial<_AllowStringsForIds<LeanDocument<DocumentType<T>>>>'.
Type 'T' is not assignable to type '_UpdateQuery<_AllowStringsForIds<LeanDocument<DocumentType<T>>>> & ReadonlyPartial<_AllowStringsForIds<LeanDocument<DocumentType<T>>>> & DotAndArrayNotation<...>'.
Type 'BaseModel' is not assignable to type '_UpdateQuery<_AllowStringsForIds<LeanDocument<DocumentType<T>>>> & ReadonlyPartial<_AllowStringsForIds<LeanDocument<DocumentType<T>>>> & DotAndArrayNotation<...>'.
Type 'BaseModel' is not assignable to type 'ReadonlyPartial<_AllowStringsForIds<LeanDocument<DocumentType<T>>>>'.
Type 'T' is not assignable to type 'ReadonlyPartial<_AllowStringsForIds<LeanDocument<DocumentType<T>>>>'.
Type 'BaseModel' is not assignable to type 'ReadonlyPartial<_AllowStringsForIds<LeanDocument<DocumentType<T>>>>'.
这个错误指向update
方法,进入item
参数里面this.model.findByIdAndUpdate(BaseService.toObjectId(item.id), item, ...);
我知道是的类型item
并且<T extends BaseModel>
它在博客文章中有效,但是为什么我在这里得到一个错误?
此外,此错误也存在:
Generic type 'Query<ResultType, DocType, THelpers>' requires between 2 and 3 type arguments.
关于count
方法,在Query<number>
.
我不明白的一件事是为什么这些错误出现在我的项目中,但没有出现在前面提到的教程中?