Я работаю над декораторами для своих методов API, и я решил эту проблему. Я пытаюсь перегрузить декораторы и получить ошибку «Эта подпись перегрузки несовместима с ее подписью реализации».
Вот фрагмент кода, который я создал:
export function ApiMethod<TResponse extends ApiResponse>(options: { methodName: string }):
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<() => Promise<TResponse>>) => void
export function ApiMethod<TResponse extends ApiResponse>(options: { methodName: string, accessPolicy: MethodAccessPolicy }):
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(payload: JwtPayload) => Promise<TResponse>>) => void
export function ApiMethod<TParams extends Object, TResponse extends ApiResponse>(options: { methodName: string, paramsType: (new (...args: Array<any>) => TParams) }):
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params: TParams) => Promise<TResponse>>) => void
// Here is the error
export function ApiMethod<TParams extends Object, TResponse extends ApiResponse>(options: { methodName: string, paramsType: (new (...args: Array<any>) => TParams), accessPolicy: MethodAccessPolicy }):
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params: TParams, payload: JwtPayload) => Promise<TResponse>>) => void
export function ApiMethod<TParams extends Object, TResponse extends ApiResponse>(options: MethodOptions | ParameterizedMethodOptions<TParams>):
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => void
{
return (target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => {
};
}
interface MethodOptions {
methodName: string;
accessPolicy?: MethodAccessPolicy;
}
interface ParameterizedMethodOptions<TParams> extends MethodOptions {
paramsType?: (new (...args: Array<any>) => TParams);
}
Я установил это общее ограничение таким образом, чтобы украшенный метод мог иметь либо параметры, либо полезную нагрузку, либо и то, и другое, в зависимости от того, какую перегрузку вы используете:
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => void
Все перегрузки работают - никакие параметры не могу задать, только пейлоад, только параметры, а пейлоад и параметры установить не могу из-за ошибки.
Любая помощь будет оценена по достоинству. Заранее спасибо.
Вы не указали тип JwtPayload
, и я предположил, что это Record<string, any>
, что позволило мне воспроизвести ошибку.
Это связано с тем, что возвращаемый тип сбойной перегрузки отличается от сигнатуры реализации.
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params: TParams, payload: JwtPayload) => Promise<TResponse>>) => void
Против
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => void
Вам нужно будет объединить возвращаемый тип:
export function ApiMethod<TParams extends Object, TResponse extends ApiResponse>(options: MethodOptions | ParameterizedMethodOptions<TParams>):
((target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params: TParams, payload: JwtPayload) => Promise<TResponse>>) => void) |
((target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => void)
{
return (target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => {
};
}
Что касается того, почему это происходит, я считаю, что это связано с тем, что TParams
является универсальным, а JwtPayload
— нет, и поэтому TS не может гарантировать, что JwtPayload
создается с тем же типом или предполагаемым типом при перегрузках.
JwtPayload — это простой объект с некоторыми свойствами.
@Lauriero Я провел несколько тестов, и похоже, вы правы. Дескриптор имеет валидацию, и в случае перегрузки 2, поскольку JwtPayload является типом объекта, он может заменить TParam, но это неверно в случае перегрузки 4. В перегрузке 4 JwtPayload назначается полезной нагрузке (как так и должно быть), но его можно создать с различными подтипами JwtPayload, поэтому эта перегрузка приводит к ошибкам. Это целая тема: stackoverflow.com/a/59363875/17954209
Большое спасибо. Я думал, что это может быть возможным решением, но я не понимаю, почему это работает. В моем вопросе во второй перегрузке у меня есть полезная нагрузка: JwtPayload, и она просто работает. Может быть, это потому, что дескриптор также проверяется на перегрузку в его параметрах, а JwtPayload заменяет TParam, потому что JwtPayload может быть TParam. Если это так, то это понятно.