Why is it possible in Angular Typescript to assign a Promise<ClassA> to an object of ClassA?

Recently, I started learning Angular and came across this snippet of code in my company's project:

currentCDFlow: CDCurrentFlowDTO;

this.currentCDFlow = await this.serivce.getCDMaster();

The code for getCDMaster() looks like this:

public async getCDMaster(): Promise<CDCurrentFlowDTO> {
    return await this.http.post<CDCurrentFlowDTO>(Constants.BASE_HREF + '/getCDMaster', null, this.RequestJson).toPromise().catch(err => { throw err });
  }

My question is, since getCDMaster() is returning a Promise<CDCurrentFlowDTO> (a Promise object), how is it allowed to be assigned to an object of type CDCurrentFlowDTO directly? I would expect it to only be assignable to an object of type Promise<CDCurrentFlowDTO>, not just CDCurrentFlowDTO without being enclosed in a Promise<...>.

In Java, for example:

String a = new ArrayList<String>();

would result in a compile error...

Is this a feature specific to TypeScript?

Answer №1

The utilization of async/await syntax enables currentCDFlow to be assigned the value from the promise. This functionality is part of ES6. Asynchronous functions are identified by the async keyword, and await pauses the process until the promise is resolved, then retrieves the result.

Answer №2

The explanation lies in the concept of a `Promise`. A promise serves as a representation of an asynchronous operation or, in simpler terms, a guarantee of a future outcome. The success of your code in the task is attributed to the utilization of the `await` keyword within the function call. By employing the `await` syntax with `Promise<T>`, the program pauses execution until the promise is fulfilled, ensuring the retrieval of the promised object. This synchronous handling accounts for the functionality...

For further enlightenment, consider exploring this resource:

Update

Let’s employ your code as an illustrative demonstration...you have the subsequent function defined

public async getCDMaster(): Promise<CDCurrentFlowDTO> {
  return await this.http.post<CDCurrentFlowDTO>(Constants.BASE_HREF + '/getCDMaster', null, this.RequestJson).toPromise().catch(err => { throw err });
}

/*
and then you call it here...
*/

// Firstly, you define the variable as of type CDCurrentFlowDTO, expecting a
// return of Promise<CDCurrentFlowDTO> so let’s see how this operates...
currentCDFlow: CDCurrentFlowDTO;

/*
Since the await syntax imposes a wait for the Promise return, the following call shall suffice
*/
this.currentCDFlow = await this.serivce.getCDMaster();

/*
Nevertheless, without the await:
*/
this.service.getCDMaster() // we anticipate the output of Promise<CDCurrentFlowDTO>

If an asynchronous execution is still desired, a solution may look like this...

//...

currentCDFlow: CDCurrentFlowDTO;

this.service.getCDMaster().then((result) => {
  currentCDFlow = result;

  //upon logging here, the value should display
  console.log(currentCDFlow);
});
// logging here would output undefined since the Promise is pending
console.log(currentCDFlow);

The inclusion of `async` in the function definition is surplus as any `async` function inherently yields a `Promise`, redundant when awaiting an existing `Promise` return...a revised approach could be

publicgetCDMaster(): Promise<CDCurrentFlowDTO> {
  return this.http.post<CDCurrentFlowDTO>(Constants.BASE_HREF + '/getCDMaster', null, this.RequestJson).toPromise().catch(err => { throw err });
}

Answer №3

Clarification on your original query

await

Utilizing await extracts the resulting value from the promise.

Therefore, the following line of code

this.currentCDFlow = await this.serivce.getCDMaster();

essentially assigns the resolved Promise value from the method to this.currentCDFlow.

If you omit await in the assignment, TypeScript will throw an error since you are attempting to assign a promise to a non-promise object.

currentCDFlow: CDCurrentFlowDTO;
this.currentCDFlow = this.serivce.getCDMaster(); //TS error

Response to the secondary question in your comment

async

Upon specifying a function with the async keyword, it will invariably result in a Promise, regardless of the operations within (including a return await ...).

Refer to this for more information:

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

Dependent on the JS version in use, it will either be managed inherently by JS (commencing from ES8) or in transpiled TS code.

Therefore, all functions below, for example, will yield a Promise. Feel free to test them within your browser's console

async function test()
{
    return "value";
}

async function test2()
{
    return Promise.resolve("value");
}

async function test3()
{
    return await Promise.resolve("value");
}

console.log(test()); //Promise {<resolved>: "value"}
console.log(test2()); //Promise {<resolved>: "value"}
console.log(test3()); //Promise {<resolved>: "value"}

Hence, return myPromise and return await myPromise typically yield similar outcomes, with particular exceptions like try/catch blocks, as elaborated here.

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

Strategies for Implementing Responsive Design in Angular and Bootstrap Shopping Cart Apps to Deliver Custom Views on Mobile and Desktop Devices

Our shopping cart application utilizes Angular and Bootstrap. We are in need of routing different pages for mobile and desktop screens. Specifically, we want the /cart route to display a different page on mobile devices compared to desktops, taking into ...

How can you notify a component, via a service, that an event has occurred using Subject or BehaviorSubject?

For my Angular 10 application, I created a service to facilitate communication between components: export class CommunicationService { private messageSubject = new Subject<Message>(); sendMessage(code: MessageCode, data?: any) { this.messag ...

How to display a festive greeting on the specific holiday date using the ngx-bootstrap datepicker

Currently, I have implemented the ngx-bootstrap datepicker for managing appointment schedules. I have disabled weekend days and holiday dates, but now there is a requirement to display a tooltip with a holiday message when hovering over a holiday date. htt ...

What could be the reason for the UnkownOperatorException failing to be thrown?

If anything other than the characters +-*/PR is entered by the user, the UnknownOperatorException should be thrown. However, there seems to be an issue with the functionality. The sample output provided below illustrates the problem. Enter an operator and ...

atom-typescript - What could be causing the unrecognized Typescript configuration options?

I'm puzzled as to why I am encountering the errors depicted in the screenshot below. Atom is indicating that my tsconfig.json file has 'project file contains invalid options' for allowJs, buildOnSave, and compileOnSave. However, according ...

Managing button spacing with Bootstrap 4 in an Angular 2 CLI application

I find it puzzling why the alignment between Bootstrap buttons within the Angular 2 CLI project is not working as expected. To address this issue, I followed the instructions to create a new Angular 2 CLI app outlined here: https://angular.io/guide/quicks ...

Eslint highlighting the initial function declaration within a Vue script

I'm currently creating a Vue file using a Typescript script, and encountering an unusual Eslint "error." https://i.sstatic.net/UXv3A.png The issue arises on line 15 with this specific complaint: Parsing error: Unexpected token, expected "," Interes ...

Why isn't Nodemon monitoring the directory in webpack-typescript-node.js?

Here are the contents of the package.json file for a TypeScript project using webpack and node.js: "scripts": { "build": "webpack", "dev:start": "nodemon --watch src --exec \"node -r dotenv/co ...

How can I ensure thorough test coverage without relying on Testbed?

We have implemented some custom form control components with decorators as follows: @Component({ selector: 'value-selector', templateUrl: './selector.component.html', styleUrls: ['./selector.component.scss'], provid ...

Transform Text into Numeric Value/Date or Null if Text is Invalid

Consider the TypeScript interface below: export interface Model { numberValue: number; dateValue: Date; } I have initialized instances of this interface by setting the properties to empty strings: let model1: Model = { numberValue: +'', ...

How to use D3 to add arrow directions to an SVG path

Within my svg path lies the representation of a shuttle track used in manufacturing processes. Every shuttle on this track moves in a distinct direction, and I wanted the svg path to visually indicate these directions for easy reference. Initially, I tried ...

Integrating Jetty and Jersey into my Java project: a comprehensive guide

My goal is to integrate Jetty into my web application for easy deployment as a standalone JAR file without the need for server configuration. I'm facing some challenges with setting up my main class to allow Jetty access to my resource classes. The tu ...

Error class not being applied by Knockout validation

I've implemented knockout validation on a text input and the validation is working correctly. However, the errorMessageClass is not being applied to the error message. I must have made a mistake in my setup, but I can't seem to identify it. My H ...

Establishing default parameters for angular pipes

Is there a way to establish default settings for an angular pipe without creating a custom one myself? I frequently utilize the currency pipe in this manner {{ price | currency:'EUR':'symbol':'0.2-2':'de' }} I&apo ...

Leveraging jQuery within a webpack module shared across multiple components, located outside the webpack root directory

When working with multiple layouts that rely on shared typescript files, it is important to ensure these files are accessible across different layouts using webpack. While attempting to include jquery in my ajax.ts, I encountered the following error: ERR ...

How can one retrieve the Title of an inner frame using Selenium WebDriver?

I'm encountering an issue in my program where I am attempting to retrieve the title of an inner frame by switching the control to it with the getTitle() method. However, instead of fetching the inner frame's title, it keeps returning the title of ...

Passing data from child to parent in Angular using EventEmitter

I have integrated a child grid component into my Angular application's parent component, and I am facing an issue with emitting data from the child to the parent. Despite using event emitter to transmit the value to the parent, the variable containing ...

Visual Studio 2015 is struggling to locate a specific module, yet the command line interface for

Recently, I delved into the world of TypeScript in VS2015 and so far, it has been a smooth journey. I managed to establish a structure that compiled and performed as anticipated. However, things took a turn when I attempted to incorporate npm-installed mo ...

PhpStorm does not currently support types in JavaScript

Currently, I am using PhpStorm for a Vue 2 / TypeScript project. However, whenever I attempt to add return types to functions, I encounter the error message "Types are not supported by current JavaScript version": https://i.sstatic.net/ct3gu.png In the " ...

The union type consisting of String, Boolean, and Number in type-graphql has encountered an error

I attempted to create a union type in type-graphql that represents the String, Number, and Boolean classes, but unfortunately, it was not successful. Does anyone have any suggestions on how to achieve this? export const NonObjectType = createUnionType({ ...