'How to define an overload signature for a function that might be called with 1 or 2 arguments?
I'm trying to define the signature for a function that might be called with 1 or 2 arguments, but I'm getting an error that the type of the function with 2 arguments is not assignable to my defined type.
The type that I defined:
type Response = {
status: string;
result: object;
}
export interface CallbackFunction {
(response: Response): void;
(error: Error | null, response?: Response): void;
}
// Example code to get the error
// OK
// res: Response | Error | null
export const fn: CallbackFunction = (res) => {
// ...
};
// Error
// Type '(err: Error | null, res: Response | undefined) => void' is not assignable to type 'CallbackFunction'.
export const fn2: CallbackFunction = (err, res) => {
// ...
};
// Error
// Argument of type '{ status: string; result: {}; }' is not assignable to parameter of type 'Error'
fn({ status: 'Test', result: {} })
The library that I'm using calls this function with only 1 argument if I'm not explicitly using the timeout option, otherwise it calls it with 2 arguments, the first will be an error on timeout or null otherwise with the second argument being the result.
I know this is not the best design, but I can't change the code, it's a third party library.
Solution 1:[1]
You should add that the first overload does not expect a second parameter like this and make it optional to match the second overload:
export interface CallbackFunction {
(response: ExampleResponse, _?: never): void;
(error: Error | null, response?: ExampleResponse): void;
}
Then it works beautifully as you can see in here:
Solution 2:[2]
It is not clear what part of the above code is modifiable and what is not. I'll assume that you can change the type declaration and the first handler.
You could change your type as follows:
type CallbackFunction =
((response: Response) => void) |
((error: Error | null, response?: Response) => void);
which is an union of two possible function overloads. However, the first example of use is ambiguous: is that the first form or the second where a parameter is omitted (useless)?
export const fn: CallbackFunction = (res: ???) => {
//
};
That is, you can adjust the code as follows and everything works fine:
export const fn: CallbackFunction = (res: Response) => {
//
};
// Error
// Type '(err: Error | null, res: Response | undefined) => void' is not assignable to type 'CallbackFunction'.
export const fn2: CallbackFunction = (err, res) => {
// ...
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
