TypeScript Mixin Распространение типа контроллера CRUD - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь настроить службы 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.

Есть ли способ получить тип безопасность в обоих классах без использования дополнительных интерфейсов?

...