I'm attempting to implement function overloading in TypeScript.
Below is the code snippet I have:
/**
* Returns a 400 Bad Request error.
*
* @returns A response with the 400 status code and a message.
*/
export function badRequest(): TypedResponse<{ message: string }>;
/**
* Returns a 400 Bad Request error.
*
* @param errors - An object containing the errors from the Zod schema.
* @returns A response with the 400 status code, a message, and the errors.
*/
export function badRequest<T>(
errors: ZodFormattedError<T>,
): TypedResponse<{ message: string; errors: ZodFormattedError<T> }>;
/**
* Returns a 400 Bad Request error.
*
* @param errors - An error string.
* @returns A response with the 400 status code, a message, and the errors.
*/
export function badRequest(
errors: string,
): TypedResponse<{ message: string; errors: string }>;
export function badRequest<T>(errors?: ZodFormattedError<T> | string) {
return json(
{ message: 'Bad Request', ...(errors && { errors }) },
{ status: 400 },
);
}
const myRequest = badRequest({
_errors: [
{
code: 'invalid_type',
expected: 'string',
received: 'number',
path: ['name'],
message: 'Expected string, received number',
},
],
});
I need TypeScript to differentiate when badRequest
is invoked without arguments, the return type includes only a message. If called with a string, it should include an errors
property containing a string. When provided with a ZodFormattedError
, the errors
property needs to be those specific errors.
The current implementation results in a TypeScript error:
No overload matches this call.
Overload 1 of 3, '(errors: ZodFormattedError<{ _errors: unknown; }, string>): TypedResponse<{ message: string; errors: ZodFormattedError<{ _errors: unknown; }, string>; }>', gave the following error.
Type '{ code: string; expected: string; received: string; path: string[]; message: string; }' is not assignable to type 'string'.
Overload 2 of 3, '(errors: string): TypedResponse<{ message: string; errors: string; }>', gave the following error.
Argument of type '{ _errors: { code: string; expected: string; received: string; path: string[]; message: string; }[]; }' is not assignable to parameter of type 'string'.
What is the correct way to overload this function?