Issue
I’m working on decorators for my API methods and I encoutered this problem. I’m trying to overload decorators and get the ‘This overload signature is not compatible with its implementation signature’ error lintered.
Here goes fragment of code I created:
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);
}
I set this general restriction like that so the decorated method can have either params or payload or both, depending on which overload you do use:
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => void
All the overloads are working – I can set no parameters whatsoever, only payload, only parameters, but I can’t set payload and parameters because of the error.
Any help would be appreciated. Thanks in advance.
Solution
You did not provide the type of JwtPayload
and I assumed it was Record<string, any>
which allowed me to reproduce the error.
This is because the return type of the failing overload is different from the implementation signature.
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params: TParams, payload: JwtPayload) => Promise<TResponse>>) => void
Versus
(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<(params?: TParams, payload?: JwtPayload) => Promise<TResponse>>) => void
You’ll have to union the return type:
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>>) => {
};
}
As for why this happens, I believe it is because TParams
is a generic while JwtPayload
is not, and as such TS cannot guarantee JwtPayload
is instantiated with the same type or intended type across overloads.
Answered By – Cody Duong
Answer Checked By – Candace Johnson (BugsFixing Volunteer)