Я пытаюсь настроить службы CRUD для своей серверной части Nest JS, используя миксины, чтобы предотвратить повторение кода. Например, миксин List
добавляет метод к классу для перечисления его сущностей. Проблема в том, что как только я применяю функцию микширования, возвращаемый класс теряет некоторые из своих типов из-за того, что общий тип, указанный для миксина, перезаписывает текущие типы классов.
Видео, объясняющее проблему: https://drive.google.com/file/d/1vA-JOpK_BkGP3iwPsNEiLL3mA4cwacdl/view
base.service.ts
export function BaseService<S extends BaseEntity>(r: Constructor<S>) {
class BaseServiceHost {
@InjectRepository(r) public repo: Repository<S>;
}
return BaseServiceHost;
}
export interface TBaseService extends Mixin<typeof BaseService> { };
list.ts <- это миксин </p>
export function ListService<TBase extends Constructor<TBaseService>> (Base: TBase) {
class A extends Base {
getList() {
return this.repo.findAndCount(); // recognizes that repo.find() will return BaseEntity type which is great as within the mixin we don't yet know what type the specific service will respond with
}
}
return A;
}
export interface TListService extends Mixin<typeof ListService> {};
account.service.ts <- класс, к которому должен применяться миксин </p>
export class AccountService extends ListService(BaseService(Account)) {
async do() {
const a = await this.repo.findOne(1); // Returns "BaseEntity" type when it should be able to deduce it as "Account" type.
}
}
mixin.type.ts <- вспомогательный файл </p>
export type Function<A = any> = (...input: any[]) => A
export type Constructor<A> = new (...input: any[]) => A
export type Mixin<T extends Function> = InstanceType<ReturnType<T>>
Если миксин List
указан с помощью <TBase extends Constructor<TBaseService>>
, я могу безопасно получить доступ к методам BaseService, и это здорово. Однако это означает, что в файле account.service.ts
он больше не распознает, что тип объекта должен быть «Учетная запись», и вместо этого использует тип BaseEntity.
Если я установил параметр типа миксина списка как <TBase extends Constructor>
вместо <TBase extends Constructor<TBaseService>>
он сохранит тип в сервисе «Account», устраняя эту проблему, но в миксине List у меня больше нет безопасного доступа к свойствам BaseService.
Есть ли способ получить тип безопасность в обоих классах без использования дополнительных интерфейсов?