Вероятно, вы хотите, чтобы ваша фабрика декораторов была не-generi c, и чтобы она производила общий c декоратор. Сейчас ваша фабрика декораторов имеет тип generi c и возвращает не-generi c декоратор. В этом разница между этими двумя:
// bad
declare const genericFactoryForSpecificFunction: <T>() => (x: T) => T;
const oops = genericFactoryForSpecificFunction()(123); // unknown
// good
declare const specificFactoryForGenericFunction: () => <T>(x: T) => T;
const okay = specificFactoryForGenericFunction()(123); // 123
В плохом случае компилятор должен вывести T
, когда вы вызываете genericFactoryForSpecificFunction()
, но нет значения типа T
, чтобы он мог проконсультироваться в это выражение. Таким образом, он выбирает unknown
, что означает, что последующий вызов аргумента 123
возвращает unknown
. В хорошем случае компилятор откладывает вывод T
до вызова функции, возвращаемой specificFactoryForGenericFunction()
. Это позволяет компилятору фактически использовать значение типа T
для вывода T
, и поэтому вы получаете 123
out.
После того, как вы внесете это изменение, вам понадобится Decorator
type должен быть определенным c типом, представляющим общую подпись вызова функции c. Я полагаю, что можно перевести ваш условный тип в эту форму, но это немного беспорядочно и использует кортежи для отдыха:
type PossibleDecorator = <T>(
target: T,
...args: T extends Function ? [] : [string?]
) => T extends Function ? T : void;
declare const pd: PossibleDecorator;
pd(RegExp); // okay, class decorator
pd({a: ""}, "a") // okay, prop decorator
pd(RegExp, "oops"); // error, tried to pass prop to class decorator
Я бы сказал, что перегрузка с несколькими вызовами-сигнатурами была бы лучше, и она имеет такое же поведение:
type Decorator = {
<T extends new (...args: any) => any>(ctor: T): T; // class decorator
<T, K extends keyof T>(proto: T, member: K): void; // prop decorator
}
declare const d: Decorator;
d(RegExp); // okay, class decorator
d({ a: "" }, "a") // okay, prop decorator
d(RegExp, "oops"); // error, tried to pass prop to class decorator
Итак, ваш примерный код будет выглядеть примерно так:
function Schema(): Decorator {
return (target: any, propertyKey?: string) => {
if (target instanceof Function) {
return target;
}
return;
};
}
@Schema()
export default class MyClass {
@Schema()
bool: boolean = false;
}
Выглядит хорошо.
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код