#typescript #mongoose #nestjs #typescript-typings
#typescript #mongoose #nestjs #typescript-типизации
Вопрос:
Я работаю над API NestJS и пытаюсь создать некоторые документы с помощью mongoose, но я сталкиваюсь с некоторыми проблемами. Я следил за документами NestJS Mongo и руководством по Auth0 API, чтобы получить хорошее представление о том, что вы должны делать.
[ПРИМЕЧАНИЕ] Я удалил все очевидные и выходящие за рамки импорта блоки кода. Я также зарегистрировал модели, какими они должны быть, так что здесь тоже не о чем спрашивать. Также необходимо, чтобы я мог заполнять значения самостоятельно, поскольку в реальном продукте я должен выполнять вычисления для заполнения значений. Вот почему я решил сначала заполнить значения, вместо того, чтобы просто передавать DTO объекту mongoose.
Это мой объект документа mongoose:
// src/user/interfaces/user.interface.ts
import { Document } from 'mongoose';
export interface User extends Document {
readonly string firstName;
readonly string lastName;
readonly string fullName;
}
Но .. когда я пытаюсь заполнить значения в сервисе следующим образом:
// src/user/user.service.ts
import { User } from './interfaces/user.interface';
@Injectable();
export class UserService {
constructor(
@InjectModel("User")
private readonly userModel: Model<User>,
) {}
async createUser(dto: CreateUserDTO): Promise<User> {
const user: User = {
firstName: dto.firstName,
lastName: dto.lastName,
fullName: `${dto.firstName} ${dto.lastName}`,
}
return await this.userModel.create(user);
}
}
Это приводит к следующей ошибке и не компилируется:
Type '{ firstName: string; lastName: string; fullName: string; }'
is missing the following properties from type 'User': increment, model, $isDeleted, remove, and 52 more.ts(2740)
Это, конечно, ошибки, поскольку он расширяет документ Mongoose, и эти значения не заполняются.
Я уже пробовал следующее, но мне не понравились «решения»
Попытка 1
Передайте это напрямую в качестве аргумента, к сожалению, это не дает мне автозаполнения и проверки
async createUser(dto: CreateUserDTO): Promise<User> {
const newUser = new this.userModel({
firstName: dto.firstName,
lastName: dto.lastName,
fullName: `${dto.firstName} ${dto.lastName}`,
});
return await newUser.save();
}
Попытка 2
Создайте второй интерфейс и используйте интерфейс A при заполнении и интерфейс B при возврате и вызове
// src/user/interfaces/user.interface.ts
import { Document } from 'mongoose';
export interface User {
readonly string firstName;
readonly string lastName;
readonly string fullName;
}
export interface UserDoc extends User, Document {}
а затем используете его в сервисе, например:
// src/user/user.service.ts
import { User, UserDoc } from './interfaces/user.interface';
@Injectable();
export class UserService {
constructor(
@InjectModel("User")
private readonly userModel: Model<UserDoc>,
) {}
async createUser(dto: CreateUserDTO): Promise<UserDoc> {
const user: User = {
firstName: dto.firstName,
lastName: dto.lastName,
fullName: `${dto.firstName} ${dto.lastName}`,
}
return await this.userModel.create(user);
}
}
Теперь это работает, но это действительно некрасиво, и вам также нужно убедиться, что вы используете правильный интерфейс в нужное время, так что это довольно неудобно.
TL; DR; Есть ли способ создать строго типизированные объекты mongoose, в которые вы можете поместить значения, которые будут автоматически заполняться, как в Attempt B
, но лучше и чище?