What is the syntax for defining parameters in an overloaded arrow function in TypeScript?

Trying to create an async arrow function that can handle a single image object or an array of image objects.

I'm new to TypeScript overloading and may be approaching this the wrong way.

Here's what I've come up with:

type ImageType = {
  uri: string;
  type?: string;
  height?: number;
  width?: number;
};

type ConvertImagesToJpegParams = {
  (param: ImageType): Promise<ImageType>;
  (param: ImageType[]): Promise<ImageType[]>;
};

const convertImagesToJpegAsync: ConvertImagesToJpegParams = async (images) => {
  const isImagesAnObject = typeof images === 'object';
  const imagesToConvert = isImagesAnObject ? [images] : images;

  let convertedImages = [];
  const convertImageToJpegPromises = imagesToConvert.map(async (image) => {
     // do stuff that converts the image.
  });
  await Promise.all(convertImageToJpegPromises);

  return isImagesAnObject ? convertedImages[0] : convertedImages;
};


  • How should I define the types for async (images)?
    If I specify images: ImageType | ImageType[], the map function gives an error.

    Property 'map' does not exist on type 'ImageType | ImageType[]'. Property 'map' does not exist on type 'ImageType'.ts(2339)

  • Once images is correctly typed, is there a more efficient way to check if isImagesAnObject? I tried something like images instanceof ImageType but it didn't work.

Answer №1

Regrettably, there doesn't seem to be a way to avoid specifically indicating the items type as either ImageType or ImageType[]. To determine if the argument is an array, you can use Array.isArray, and then proceed with either returning a mapped Promise.all for the asynchronous operation on the array, or simply executing the asynchronous operation on the individual item:

const convertImagesToJpegAsync: ConvertImagesToJpegParams = async (images: ImageType | ImageType[]) => {
    return Array.isArray(images)
        ? Promise.all(images.map(Promise.resolve)) // insert your actual async operation here
        : Promise.resolve(images); // insert your actual async operation here
};

Typescript is able to deduce the type of the parameters and their corresponding return types effectively even without the need for the ConvertImagesToJpegParams; thus, it is acceptable to exclude it (and entirely remove that type definition):

const convertImagesToJpegAsync = async (images: ImageType | ImageType[]) => {
    return Array.isArray(images)
        ? Promise.all(images.map(Promise.resolve))
        : Promise.resolve(images);
};

Answer №2

Regrettably, this task cannot be accomplished as it is a runtime check. Nevertheless, you can utilize a type-guard to reach your desired outcome:

type ImageType = {
  uri: string;
  type?: string;
  height?: number;
  width?: number;
};

type ConvertImagesToJpegParams = {
    (...param: ImageType[]): Promise<ImageType[] | ImageType>;
};


// Implementing a Type guard for an array response
const isArray = <T extends object>(images: T | T[]): images is T[] => {
    return Array.isArray(images);
}


// Implementing a Type guard for an object response
const isObject = <T extends object>(images: T | T[]): images is T => {
    return !Array.isArray(images);
}

const convertImagesToJpegAsync: ConvertImagesToJpegParams = async (...images) => {
    if (images.length === 0) {
        // edge case; should probably throw an exception
    }

    const convertedImages: ImageType[] = [];
    const promises = images.map(async (image) => {
        // perform operations here
    });

    await Promise.all(promises);

    return images.length === 1
        ? convertedImages[0]
        : convertedImages;
};

// Now let's see how to use it

const result = await convertImagesToJpegAsync();
if (isObject(result)) {
   // now you have access to result.uri        
}
if (isArray(result)) {
  // now you can iterate through result.forEach
}

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

Change the <base> element programmatically during server-side rendering

Searching for a way to obtain the base URL for an HTML page, so that relative URL requests from the browser utilize that base. If you are looking for answers, check out this link: Defining root of HTML in a folder within the site root folder When serving ...

Solving Angular Circular Dependencies

My popupservice allows me to easily open popup components: export class PopupService { alert() { this.matdialog.open(PopupAlertComponent); } yesno() { this.matdialog.open(PopupYesNoComponent); } custom() { this.matdialog.open(PopupCustomCompon ...

What is the method to have the text cursor within a text field start a few pixels in?

I need a text field with the cursor starting a few pixels (let's say 4) from the left-hand side. I am aware that this can be achieved by adjusting the size of the text field using padding, but I am curious if there is a way to resize the text box with ...

Warning: Potential spacing issues when dynamically adjusting Material UI Grid using Typescript

When working with Typescript, I encountered an error related to spacing values: TS2322: Type 'number' is not assignable to type 'boolean | 7 | 2 | 10 | 1 | 3 | 4 | 5 | 6 | 8 | "auto" | 9 | 11 | 12'. No lint errors found Version: typesc ...

NextJs not processing Bootstrap form submissions

I’m struggling to figure out why my form isn’t submitting when I click the submit button. The backend seems fine because Postman successfully sends the information to the database. However, nothing happens when I try to submit the form. My tech stack ...

The JavaScript program is occasionally receiving unconventional input

I'm really struggling with this one. As part of a programming exercise, I am developing a JavaScript calculator. You can access the functioning calculator here on Codepen. At the bottom left corner of the calculator interface, you will notice a "+-" ...

How can you transfer data from a jQuery function to a designated div element?

I'm struggling to transfer data from a function to a specific div, but I can't seem to make it work. I'm in the process of creating a gallery viewer and all I want is to pass the counter variable, which I use to display images, and the total ...

Having trouble accessing @ViewChildren from the parent component

I've been facing an issue while attempting to control the child instances of a component and I can't seem to bypass this particular error. I've been referring to solutions provided on this specific thread. The main component Sequence houses ...

Using jQuery to compel a user to choose a value from the autocomplete suggestions within a textarea

Currently, I have implemented a snippet that allows the user to choose cities from a list and insert them into a textarea separated by commas. However, I am looking to enhance this feature. I want the user to be able to search for a city by typing a part ...

The dictionary of parameters has an empty entry for the 'wantedids' parameter, which is of a non-nullable type 'System.Int32', in the 'System.Web.Mvc.JsonResult' method

The console is showing me an error stating that the parameters dictionary contains a null entry for parameter wantedids. I am trying to pass checked boxes to my controller using an array, so only the admin can check all boxes of tips for a specific user. T ...

including a code snippet within a dropdown menu or embedding it in a clickable button

Hey there, my name is Wouter Sanders and I am currently learning to code! I recently finished creating a RAL color picker for a project I'm working on. The only issue I've run into is trying to embed the code in a menu or button so that it doesn ...

The no-unused-expressions rule is triggered when an assignment or function call is expected

I'm just starting out in full stack development and I'm experimenting with coding to improve my understanding of frontend using React JS and Material UI. While working on this component, I encountered an error in the console at line 75 (this.prop ...

What is the best way to retrieve strings from an asynchronous POST request?

I am currently working on implementing a signup function in my Angular app using a controller and a factory. However, I am facing an issue where the strings (associated with success or failure) are not being returned from the factory to the controller as e ...

Having difficulty generating dynamic rows and tree dropdowns in AngularJS

Struggling to implement dynamic row functionality with Angular JS. The rows are working well, but I also need to incorporate a tree dropdown within each row. Unfortunately, clicking the "add row" button populates the same data in all rows. I have shared m ...

When attempting to utilize a global variable in a POST request, it may be found to

My dilemma is that I can successfully access the global variable in other requests such as 'GET', but it becomes undefined when used in a 'POST' request. var dirName; app.post("/addFace", function (req, res) { //create directory con ...

Connecting nodes to edges based on their unique ids in the d3.js graph library

I am encountering an issue with this code while trying to integrate it with a new JSON object called 'new_json'. Specifically, I need the links in this code to be created based on the nodes' IDs. Can anyone provide assistance with this? va ...

Creating a captivating animation for a social media like button with CSS

I came across some animation code on the web and noticed that when I click the image, it replays the animation from the starting point. I want to make it so that when I click the image, the animation plays and stops, and if clicked again, resets the image. ...

Navigate the JSON object at predetermined intervals, such as in the case of movie subtitles

Apologies if the title is not specific enough, open to any suggestions for improvement. Here's my issue: I have a JSON file (presented here as a JavaScript object) that contains subtitles for a movie. My goal is to display the text exactly as it appea ...

Is it possible to transfer a variable from my javascript code to a jsp file?

Within a HTML file, I have created a variable in JavaScript consisting of an array with two entries - a latitude and a longitude. I am looking to use AJAX to send this variable and then utilize it in my JSP file to populate a form. Does anyone have any su ...

Enforcing alias types in TypeScript arguments is necessary for maintaining consistency and clarity

I'm currently facing a challenge with type unions and aliases. I have an alias for values that can possibly be null or undefined, along with a function that handles these values. Everything is running smoothly and safely. However, there are instances ...