I'm using typegoose with strictNullChecks enabled, however when I want to speicfy return type, it never gets right. I have created a base typegoose model and service for others to extend from.
base.model.ts
import { modelOptions, prop } from '@typegoose/typegoose';
@modelOptions({
schemaOptions: {
id: false,
toJSON: {
getters: true,
virtuals: true,
versionKey: false
}
}
})
export abstract class BaseModel {
public _id: string;
@prop({ index: true, default: Date.now })
createdAt: Date;
@prop({ index: true, default: Date.now })
updatedAt: Date;
}
base.service.ts
import { ReturnModelType } from '@typegoose/typegoose';
import { AnyParamConstructor, DocumentType } from '@typegoose/typegoose/lib/types';
import { FilterQuery, UpdateQuery } from 'mongoose';
import { BaseModel } from './base.model';
export abstract class BaseService<T extends BaseModel> {
protected model: ReturnModelType<AnyParamConstructor<T>>;
protected constructor(model: ReturnModelType<AnyParamConstructor<T>>) {
this.model = model;
}
findOne(filter: FilterQuery<T>) {
return this.model.findOne(filter);
}
findAll(filter: FilterQuery<T>) {
return this.model.find(filter);
}
findById(id: string) {
return this.model.findById(id);
}
aggregate() {
return this.model.aggregate();
}
create(item: Partial<T>) {
return this.model.create(item);
}
delete(filter: FilterQuery<T>) {
return this.model.findOneAndDelete(filter);
}
deleteById(id: string) {
return this.model.findByIdAndDelete(id);
}
update(filter: FilterQuery<T>, item: UpdateQuery<DocumentType<T, object>>) {
return this.model.findOneAndUpdate(filter, item, { new: true });
}
updateById(id: string, item: UpdateQuery<DocumentType<T, object>>) {
return this.model.findByIdAndUpdate(id, item, { new: true });
}
count(filter: FilterQuery<T>) {
return this.model.countDocuments(filter);
}
async findOneAsync(filter: FilterQuery<T>): Promise<T> {
return this.findOne(filter);
}
async findAllAsync(filter: FilterQuery<T>) {
return this.findAll(filter);
}
async findByIdAsync(id: string) {
return this.findById(id);
}
async createAsync(item: Partial<T>) {
return this.create(item);
}
async deleteAsync(filter: FilterQuery<T>) {
return this.delete(filter).exec();
}
async deleteByIdAsync(id: string) {
return this.deleteById(id).exec();
}
async updateAsync(filter: FilterQuery<T>, item: UpdateQuery<DocumentType<T, object>>) {
return this.update(filter, item).exec();
}
async updateByIdAsync(id: string, item: UpdateQuery<DocumentType<T, object>>) {
return await this.updateById(id, item).exec();
}
async countAsync(filter: FilterQuery<T>) {
return await this.count(filter);
}
}
I want to add the return type Promise<T | null> to functions like findByIdAsync, however it gave me this incredibly long error:
Type 'IfAny<T, any, Document<unknown, BeAnObject, T> & Omit<Require_id<T>, "typegooseName"> & IObjectWithTypegooseFunction> | null' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'IfAny<T, any, Document<unknown, BeAnObject, T> & Omit<Require_id<T>, "typegooseName"> & IObjectWithTypegooseFunction> | null'.
Changing Promise<T> to Promise<DocumentType<T, object>> does not work as well, I don't know what is IfAny at all