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

How can express.js be properly installed using typescript?

Currently, I am in the process of setting up a new project that involves using express.js with typescript integration. Would it suffice to just install @types/express by running the following command: npm install @types/express Alternatively, do I also ...

Refreshing a section of a webpage using AJAX and PHP

After creating a RESTful API in PHP, I can easily register information by accessing the address . This registration process involves sending a POST request. Below is an overview of my method: File: api.php <?php /* File: api.php */ private function ...

Issue: When a function within a subscribe method does not return a value and its declared type is not 'void' or 'any', a TypeScript error occurs

In my Angular 2 project, I've created a basic service to check if the user is logged in. This service verifies the existence of the user object within the FirebaseAuth object. However, I encountered an error stating "lack of return statement" even tho ...

What is an example scenario where Async Storage can be tested using Jest-expo?

To better understand the testing of Mock-async-storage for reactjs, I decided to replicate an example. If you have any suggestions on a different approach to testing, please feel free to share. I attempted to mimic a use case illustrated on this stack over ...

Error in JSLint Object Detection

Currently using JSLint to scan the code below: 'use strict'; var mathService = { add: add, subtract: subtract, multiply: multiply, divide: divide, power: power, squareRoot: squareRoot }; function add(first, second) { retur ...

Modify the classname of two element class i

I am trying to change the class on click within an <i> element that has 2 classes. The first class is always "fa" and the second class can be either "fa-minus" or "fa-plus". I need to toggle between "minus" and "plus" based on the current class. Ca ...

hiding html elements by using the display property set to none instead of physically removing

I am currently utilizing an if-else statement to display different HTML structures. As a result, the entire HTML is being rendered twice. Is there a way we can utilize 'display: none' instead? I attempted to use it in th ...

Guide on how to turn off cache in AngularJS + NodeJS CRUD application

I'm encountering an issue with cache in Internet Explorer, but everything seems to be working fine in Chrome. Whenever I try to add an item in my application, the data doesn't refresh automatically and I have to press Ctrl+R to manually refresh. ...

Updating NodeJs to Express 4.0 may result in encountering errors

Hey there, I've been diving into node.JS and the express module recently and came across this helpful resource link However, when attempting to update the dependencies to express 4.0 in the example provided, it seems to break. I understand that app.c ...

Having difficulty implementing a personalized color scheme for the mui component

Attempting to set the background color as midnightBlue but encountering an error: Error: Cannot read properties of undefined (reading '100') Upon reviewing the syntax, no errors were found. Perhaps this issue stems from a dependency problem? ...

End all occurrences of XMLHttpRequest

In my code, I am calling the function SigWebRefresh at specific intervals of 50 milliseconds. tmr = setInterval(SigWebRefresh, 50); The function SigWebRefresh utilizes XMLHTTPRequest: function SigWebRefresh(){ xhr2 = new XMLHttpRequest(); ...

Implementing dropdown filtering for nested ng-repeats in Angular application

I currently have the following data structure set up: vm.years = [{ year: number, proevents: [{year: number, division: string, level: string, place: string, names: string}], nonproevents: [{year: number, division: string, level: string, place: st ...

Issue with loading the main.css file

Getting Started Managing two domains can be a challenge, especially when trying to make them appear as one seamless website. In this case, I have ownership of and . Goal My goal is to merge the content of https://mauricevandorst.com/personal-page/index ...

What is the reason javascript struggles to locate and replace strings with spaces in a URL?

Let me begin by sharing the code I'm currently working on so that you can easily follow my explanations. Apologies for the French language used, as this website is being developed for a French-speaking school. I have eliminated irrelevant sections fro ...

Using Typescript for testing React components: successfully passing an array of objects as props

My current approach involves passing an array of objects to mock component data for testing: const mockPackage = { id: '1232-1234-12321-12321', name: 'Mock Package', price: 8.32, description: 'Mock description', glo ...

The specific type of selection return type in Prisma is restricted

My Prisma schema is structured like this: model Sample { id String @id @default(cuid()) createdOn DateTime @default(now()) category String } category should STRICTLY belong to one of these options: const Categories = [ "alphaC ...

Increase the bottom padding or add some extra space to the Bootstrap form or page

I am currently working on enhancing a Bootstrap Form that includes reset/submit buttons positioned at the bottom. A common issue is when iPhone users attempt to click the Submit button, which initially displays Safari icons before requiring an extra tap to ...

The script functions perfectly in jsfiddle, yet encounters issues when used in an HTML

I stumbled upon a seemingly peculiar issue with my script in jsfiddle: https://jsfiddle.net/oxw4e5yh/ Interestingly, the same script does not seem to work when embedded in an HTML document: <!DOCTYPE html> <html lang="en"> <head> & ...

How to handle form-data in NestJS Guards?

I've been trying to access form-data in my NestJS Guards, but I'm experiencing some difficulties. Despite following the tutorial provided here, I am unable to see the request body for my form-data input within the Guard itself. However, once I ac ...

Toggling with Jquery when an image is clicked

I'm trying to wrap my head around the functionality of jquery toggle. My goal is to toggle to the next anchor element with the class plr-anchor when an image with the class go_down is clicked. The information is being populated using maps. Javascript ...