#typescript #types #casting #nestjs
#typescript #типы #Кастинг #nestjs
Вопрос:
Во-первых, вот основной интерфейс :
// IMySuperInterface.interface.ts
export interface IMySuperInterface<T = any> {
handle(arg?: any): Promise<T>;
}
По сути, мне просто нужен общий тип для ==> дочернего класса с функцией ‘handle’.
Что-то вроде :
function MyDummyFunction (param: {{class that extends IMySuperInterface)}})
Я пытаюсь зарегистрировать все классы в моем приложении, которые реализуют мой «IMySyperInterface»
// MySuperImplementation.service.ts
@Feature('ReferenceA')
export class MySuperImplementation
implements IMySuperInterface {
constructor(private readonly logger: myLoggerService) {
this.logger.setContext(this);
}
async handle(someDummy: any): Promise<void> {
....
}
}
И здесь определение декоратора
// feature.decorator.ts
const _mapping = new Map<string, anyOrIdontKnowWhatToDo>();
export function Feature(key: string) {
return function (target: **HERE WHAT CAN I WRITE ??????**) {
Feature.cache.set(key, target);
return target;
};
}
Я пытаюсь найти какой-то «по крайней мере, содержит <IMySuperInterface>» или тип <IMySuperInterface>
с
export interface Type<T = any> extends Function {
new (...args: any[]): T;
}
Но я получаю :
- ни то, ни другое: извините, но ‘prototype’ отсутствует в IMySuperInterface
- ни то, ни другое: извините, но вход в систему несовместим с типом ‘Type’
Я потерялся: (.. Как я могу определить в качестве параметра моей функции класс, который реализует мой интерфейс? Примечание: аргумент в конструкторе моего класса постоянно меняется, а также аргумент функции в интерфейсе.
Комментарии:
1. Мне трудно понять, чего вы пытаетесь достичь здесь. Где
handle
на самом деле вызывается и какие аргументы вы ему передаете? Наличие необязательного аргумента вinterface
почти наверняка не то, что вы хотите, поскольку это означает, что реализации не могут требовать никаких аргументов. Либо аргументы определены и известны, либоhandle
это функция, которая не принимает аргументов.2. Я не верю, что возможно, чтобы декоратор применялся исключительно к классам, которые реализуют определенный интерфейс. Я хотел бы, чтобы это было так, но, насколько мне известно, это невыполнимо
3. @LindaPaiste спасибо за ваш комментарий, я добавляю функцию дескриптора в класс. Я понимаю ваше предупреждение о необязательных аргументах в интерфейсе, но я не могу четко предсказать входящий элемент здесь.
4. @JayMcDoniel На самом деле вы можете ограничить область применения декоратора, изменив тип целевых параметров в определении декоратора
Ответ №1:
Сегодня я узнал, что можно вводить декоратор для определенных классов. В любом случае, я смог реализовать что-то подобное, подобное этому:
export function Command(
options: CommandMetadata,
): <TFunction extends CommandRunner>(target: TFunction) => void | TFunction {
return (target) => {
Reflect.defineMetadata(CommandMeta, options, target);
return target;
};
}
Это полностью типизированный декоратор, вместо того, чтобы использовать ClassDecorator
тип, чтобы я мог правильно установить target
общий тип. Должно быть примерно то, что вы ищете. Просто CommandRunner
замените свой интерфейс и возврат функции anon target
логикой вашего декоратора.
Комментарии:
1. Ты убийца, ответ правильный, но для меня он был полностью хорош, вот ответ:
export function Feature<K extends string>( key: K, ): <TFunction extends Class<IFeature>>( target: TFunction, ) => void | TFunction { return (target) => { Feature.cache.set(key, target); return target; }; }
с помощью class =export type Class<T = unknown, Arguments extends any[] = any[]> = new ( ...arguments_: Arguments ) => T;