"Define a TypeScript function type that can return either an object or a string depending on whether it succeeds or fails

I encountered an issue with a function that either returns a Promise on success or a string on error.

async create(createDebtorDto: CreateDebtorDto): Promise<Debtor> {
    console.log("createDebtorDto", createDebtorDto)
    try{
      const createdDebtor = new this.debtorModel(createDebtorDto);
      return await createdDebtor.save();
    }catch(err){
      console.log('err', err)
        return `Unable to create debtor ${err}`;
    }
  }

During the transpilation process, I encountered this error message:

src/debtors/debtors.service.ts(19,5): error TS2322: Type 'string' is not assignable to type 'Debtor'.

This situation made me question whether it's possible to define a function that returns a Promise in case of success and a String when encountering an error without compromising the benefits of static typing.

Is it feasible to have a function that returns a promise on success and a string on error?

Answer №1

One way to approach this situation is by specifying that the output could potentially be any of those two types:

: Promise<Debtor | string>

However, it's more common for individuals to anticipate handling errors properly:

async create(createDebtorDto: CreateDebtorDto): Promise<Debtor> {
    console.log("createDebtorDto", createDebtorDto)
    try {
        const createdDebtor = new this.debtorModel(createDebtorDto);
        return await createdDebtor.save();
    } catch (err) {
        console.log('err', err)
        throw `Unable to create debtor ${err}`;
    }
}

This method should be invoked in the following manner:

myInstance.create(dto).then((debtor) => {
    // perform actions with debtor...
}).catch((error) => {
    alert(error);
});

By adhering to this practice, there is no need to verify the type of debtor within the resolve handler - thereby avoiding unexpected outcomes for individuals accustomed to working with asynchronous operations and promises.

Answer №2

It is important to note that your function always returns a Promise due to the presence of the catch statement following an await, which makes it dependent on an asynchronous value. Additionally, async methods are required to return a promise. Therefore, you should ensure that your function returns a Promise<Debtor| string> as the result of the async operation can either be a string (in case of an error) or a Debtor in case of success.

async create(createDebtorDto: CreateDebtorDto): Promise<Debtor| string> {
    console.log("createDebtorDto", createDebtorDto)
    try{
        const createdDebtor = new this.debtorModel(createDebtorDto);
        return await createdDebtor.save();
    }catch(err){
        console.log('err', err)
        return `Unable to create debtor ${err}`;
    }
}

Note: It may not be ideal design to return a string in case of an error. Consider throwing an exception and catching it in the caller instead.

async create(createDebtorDto: CreateDebtorDto): Promise<Debtor> {
    console.log("createDebtorDto", createDebtorDto)
    try{
        const createdDebtor = new this.debtorModel(createDebtorDto);
        return await createdDebtor.save();
    }catch(err){
        console.log('err', err)
        throw `Unable to create debtor ${err}`;
    }
}

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

When attempting to utilize expo-av in a React-Native project on iOS, the recorded MP4 file encountered an issue when trying to submit it as form data for Open

I've been working tirelessly through the night, trying to record myself on my iPhone using expo-av to capture speech and then upload it to openai's transcriptions endpoint with the whisper-1 model. The recording is saved as an mp4 file, which I ...

How can I set up multiple queues in NestJs Bull?

My goal is to set up multiple queues in NestJs, and according to the documentation: You can create multiple queues by providing multiple comma-separated configuration objects to the registerQueue() method. However, I am encountering an issue where VSco ...

When implementing 'useGlobalGuards' in NestJS, remember to exclude endpoints for enhanced security

After implementing the useGlobalGuards method in my main.ts file, all endpoints now utilize the AuthGuard. This guard triggers a 401 error if a valid auth token is not present in the request header. Previously, I used @UseGuards(AuthGuard) on individual cl ...

The Relationship between Field and Parameter Types in TypeScript

I am currently working on a versatile component that allows for the creation of tables based on column configurations. Each row in the table is represented by a specific data model: export interface Record { attribute1: string, attribute2: { subAt ...

What is the best way to retrieve the value from a Material UI textfield after hitting the enter key

Having trouble retrieving input values with the provided code. Attempted using onKeyUp, onKeyDown, and onKeyPress, but none of them returned the value as desired. Typically, I would use the onChange property to get the value, but it triggers for every ne ...

How can you extract the property names of the first object in an array of objects?

I have an array of objects with the following structure and I want to extract the property names of the first object from this array without including the values. The desired result should only be ["Name", "Account", "Status"] ...

Check out the uploaded file preview on React Native Expo!

I'm attempting to display a preview of the file uploaded by the user, which could be in pdf, img, or doc format. I tried a method that previews the file using a specific URL, but what I really want is for it to only show the preview of the uploaded fi ...

Developing an Angular filter using pipes and mapping techniques

I am relatively new to working with Angular and I have encountered a challenge in creating a filter for a specific value. Within my component, I have the following: myData$: Observable<MyInterface> The interface structure is outlined below: export ...

Having trouble getting the npm package with @emotion/react and vite to function properly

Encountering an issue with the npm package dependencies after publishing, specifically with @emotion/react. This problem arose while using vite for packaging. Upon installing the package in another project, the css property appears as css="[object Ob ...

The ngxpagination template is currently experiencing issues with filtering and pagination functionality

I have encountered an issue with my custom pagination template using ngx-pagination. Everything works fine until I introduce a filter pipe alongside the pagination. The problem arises when the filtered data set is not properly paginated - instead of displa ...

Find keys in an array based on a specified value

I need to retrieve an array of keys from an object that match a specified value ...

Unlocking the ability to retrieve data generated by the context within getServerSideProps beyond its boundaries (for transitioning from Create React App to Next.js)

I am currently utilizing Create React App for my react application but I am in the process of migrating to Next.js. Accessing URL data such as host, protocol, and query parameters has posed a significant challenge. After some trial and error, I realized t ...

Tips for testing and verifying the call to a specific Firebase method within a function using Jest

Within the file App.ts, I am utilizing the method firebase.auth().signInWithEmailAndPassword(email, password). Now, my objective is to conduct a unit test to ensure that when the myAuthenticationPlugin.authenticate(email, password) method is invoked from ...

Using ngx-bootstrap typeahead with custom itemTemplate for objects

I've created a custom ngx-bootstrap/typeahead component for my ngx-formly generated forms. This component fetches search results from an API and is designed to be reusable for various objects, making it dynamic. My goal is to have the typeahead retri ...

Trouble with Nextjs link not functioning properly with a URL object when incorporating element id into the pathname

Recently I added translations to my website, which means I now need to use a URL object when creating links. Everything has been going smoothly with this change except for one issue: when I try to click a link that points to /#contact. When simply using h ...

Using Typescript: What is the best way to convert a variable into a specific element of an array?

List of Strings: const myStrings = ["one", "two", "three"]; const newString = "two"; The variable newString is currently just a string, but I would like its type to be an element of myStrings. Is there a way to achi ...

Encountering the "Unrecognized teardown 1" error when subscribing to an Observable in Typescript and Angular2

Having trouble with using an Observable in my Angular2.rc.4 Typescript app. Check out the plunker for it here: https://embed.plnkr.co/UjcdCmN6hSkdKt27ezyI/ The issue revolves around a service that contains this code: private messageSender : Observable< ...

Enhancing Angular functionality with the addition of values to an array in a separate component

I need help with adding a value to an array in the 2nd component when a button in the 1st component is clicked. I am working on Angular 4. How can I achieve this? @Component({ selector: 'app-sibling', template: ` {{message}} <butt ...

The quantity of documents queried does not align with the number of data counts retrieved from Firestore

Facing an issue with calculating the Firestore read count as it keeps increasing rapidly even with only around 15 user documents. The count surges by 100 with each page reload and sometimes increases on its own without any action from me. Could this be due ...

Unable to locate the module '@vitejs/plugin-react' or its associated type

After creating the project with npm create vite@latest and selecting ts-react, everything seemed to work fine when I ran npm run dev. However, in my vs code editor, I encountered the error message "Cannot find module '@vitejs/plugin-react' or its ...