Using TypeScript: Defining function overloads with a choice of either a string or a custom object as argument

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?

Answer №1

Solved the issue by implementing these different versions:

/**
 * Generates a 400 Bad Request response.
 *
 * @returns A response with the 400 status code and a message.
 */
export function badRequest(): TypedResponse<{ message: string }>;
/**
 * Generates a 400 Bad Request response.
 *
 * @param errors - An object containing 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> }>;
/**
 * Generates a 400 Bad Request response.
 *
 * @param errors - A string containing errors.
 * @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,
): TypedResponse<{ message: string; errors?: ZodFormattedError<T> | string }> {
  return json(
    { message: 'Bad Request', ...(errors && { errors }) },
    { status: 400 },
  );
}

Answer №2

Latest response

After reviewing the official documentation, I have found that typescript does indeed support function overloading. A special thanks to Hesters for providing the helpful link.

The issue in your code lies in the mismatch between the type of parameters for which the function has been overloaded and the type of parameters you are attempting to use when calling it.

According to the implementation, the badRequest method can be invoked with either no parameters, a string type, or a ZodFormatter type. However, attempting to call it with a list of ZodFormatter types is what's causing the problem.

Referring to the provided code snippet, the method has overloads for no parameters, string, and number types. When called with an undefined list of numbers (which is not specified), it results in an error. On the other hand, when correctly invoked with the appropriate arguments, it executes without any issues.

Answer №3

For the second signature, it seems like you actually meant:

export function handleBadRequest<T extends<any, any>>(
  errors: T,
): TypedResponse<{ message: string; errors: T }>;

By making this change, your TypeScript error should be resolved.

Keep in mind that the original

ZodFormattedError<T,U=string>
interface defaults its second type parameter to string. You will need to explicitly specify a type value for that second position in order to override the default. In this case, I have used any, but feel free to choose a more specific constraint if needed.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the reason behind having to press the Tab button twice for it to work?

Currently, I am implementing a Tabbed Form with jQuery Functionality in Angular 4. The Tabbed Form itself is functioning, but I've noticed that I have to click the Tab Button twice for it to respond. See the code snippet below: TS declare var jquery ...

Having trouble establishing a connection with Db2 while using protractor

Encountering an issue when attempting to establish a connection with a remote DB2 database, resulting in the following exception: SQL30081N A communication error has been detected. The communication protocol in use is 'TCP/IP'. The com ...

What steps do I need to take for webpack to locate angular modules?

I'm currently in the process of setting up a basic application using Angular 1 alongside Typescript 2 and Webpack. Everything runs smoothly until I attempt to incorporate an external module, such as angular-ui-router. An error consistently arises ind ...

Tips for navigating the material ui Expanded attribute within the Expansion Panel

After looking at the image provided through this link: https://i.stack.imgur.com/kvELU.png I was faced with the task of making the expansion panel, specifically when it is active, take up 100% of its current Div space. While setting height: 100% did achi ...

Mastering the proper implementation of the factory method in TypeScript

Trying to articulate this question is proving to be a challenge, but I'll give it my best shot. In Sharepoint, a default ListItem comes with properties like id, title, createdby, createddate, modifiedby, and modifieddate. Custom lists can have addit ...

Router failure resulted in an internal server error

When navigating to a page in my router, I make a REST API request to retrieve data from the server in the beforeEnter clause as shown below: beforeEnter: (to, form, next) => { getData().then( (response) => { ...

I'm having trouble locating a declaration file for the module 'vue-prism-component'

Currently utilizing Vue 3 (Composition API), Vite, and Typescript but encountering a missing module issue with vue-prism-component. <script lang="ts" setup> import 'prismjs' import 'prismjs/themes/prism-tomorrow.css' imp ...

Issues arise when using Android BluetoothLeAdvertiser in Nativescript applications

I've been working on creating a Nativescript application that can send Bluetooth low energy advertisements. Since there are no existing Nativescript plugins for this functionality, I decided to develop a Java library (with plans to add a Swift library ...

In Angular, the object may be null

click here for image Encountering an error message stating that Object is possibly 'null' when utilizing querySelector and addEventListener in Angular. ...

Make Ionic 2 Navbar exclusively utilize setRoot() instead of pop()

When navigating to a different page, the ion-navbar component automatically includes a back button that uses the pop() method to return to the previous page. Is there a way to modify this behavior so that it utilizes the setRoot() method instead of pop(), ...

What is the proper way to address the error message regarding requestAnimationFrame exceeding the permitted time limit?

My Angular application is quite complex and relies heavily on pure cesium. Upon startup, I am encountering numerous warnings such as: Violation ‘requestAnimationFrame’ handler took 742ms. Violation ‘load’ handler took 80ms. I attempted to resolve ...

Exploring the TypeScript Type System: Challenges with Arrays Generated and Constant Assertions

I am currently grappling with a core comprehension issue regarding TypeScript, which is highlighted in the code snippet below. I am seeking clarification on why a generated array does not function as expected and if there is a potential solution to this pr ...

After inputting the required parameters for the React onChange event, an unexpected error persists despite my efforts

I'm struggling with a bug in my React / typescript code. I have created a custom Input component that includes an 'onChange' property as described below: onChange?: (value?: string, event?: React.ChangeEvent<any>) => void; Here is ...

Retrieve the value of a hidden input when a button is clicked using reactive forms in Angular

I am currently attempting to retrieve the values of hidden input fields that are dynamically added when the user clicks on the "insert more" button. If you'd like to view the code in action, you can visit this StackBlitz link: get hidden input value ...

How to arrange data in angular/typescript in either ascending or descending order based on object key

Hey there! I'm fairly new to Angular and have been working on developing a COVID-19 app using Angular. This app consists of two main components - the State component and the District component. The State component displays a table listing all states, ...

What causes the website to malfunction when I refresh the page?

I utilized a Fuse template to construct my angular project. However, upon reloading the page, I encountered broken website elements. The error message displayed is as follows: Server Error 404 - File or directory not found. The resource you are looking fo ...

Encountering tsconfig.json issues following the integration of Tailwindcss v3 into Next.js (create-next-app --typescipt)

Upon opening my code in VS Code, I encountered the following error: Cannot find type definition file for 'accepts'. The file is in the program because: Entry point for implicit type library 'accepts' In an attempt to resolve this issue ...

Transform TypeScript class into an object

Is there a way to transfer all values from one typescript class, Class A, to another matching class, Class B? Could there be a method to extract all properties of Class A as an object? ...

Is my implementation of this [^{}]+(?=}) regex pattern in TypeScript accurate?

Hey there! I'm currently working on extracting values that are inside curly braces "{value}". Do you think the regular expression [^{}]+(?=}) I am using is correct? let url = "/{id}/{name}/{age}"; let params = url.match('[^{\}]+(? ...

What is the best way to ensure that the operations are not completed until they finish their work using RX

Is there a way to make RXJS wait until it finishes its work? Here is the function I am using: getLastOrderBeta() { return this.db.list(`Ring/${localStorage.getItem('localstorage')}`, { query: { equalTo: fa ...