Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the result type of a Promise< > in TypeScript

For some Typescript methods I build, often I need the asynchronicity of a promise but I do not require the promise to return a value (conceptually speaking). A simple example might be calling an initLanguageStrings( ) method to load up language strings used by an application. The language strings are placed into a global structure but the promise is still necessary to ensure the application does not continue until after the language strings are loaded.

Multiple this scenario two or three times and I then tie all of the initialisation work into a set of promises that collectively must all be completed before continuing. I therefore use Promise.all, like so (example):

initialiseApp( ): Promise< void >
{
    let promises: Promise< any >[ ] = [ ];

    promises.push( this.initLanguageStrings( ) );
    promises.push( this.initModelData( ) );
    promises.push( this.initUserInfo( ) );

    return Promise.all( promises );
}

The above code won't actually compile (TS1.5/1.6) because Promise.all( ) returns Promise< any[ ] > not Promise< void >.

So what I end up writing is this:

return new Promise( ( resolve, reject ) => {
   Promise.all( promises )
      .then( ( dummy: any[ ] ) => {
         resolve( );
      } );         
} );

I believe this is semantically the correct approach, because the "implementation" actually remains hidden, and the "inner promise" (from Promise.all) never "escapes" to the caller of initialiseApp( ).

But on the other hand I find this approach ugly, and would like to find a nicer way to do this, since returning Promise< void > is becoming quite a common pattern for me.

Is there a better way to achieve what I am trying to do?

The compiler will permit:

return Promise.all( promises ).then( ( ) => { } );

But it too strikes me as "tricky" and ugly.

like image 813
Kevmeister68 Avatar asked Oct 06 '15 02:10

Kevmeister68


People also ask

How do I change the return type of promise?

Use the Awaited utility type to get the return type of a promise in TypeScript, e.g. type A = Awaited<Promise<string>> . The Awaited utility type is used to recursively unwrap Promises and get their return type. Copied!

How do you define a type of promise in TypeScript?

In TypeScript, promise type takes an inner function, which further accepts resolve and rejects as parameters. Promise accepts a callback function as parameters, and in turn, the callback function accepts two other parameters, resolve and reject. If the condition is true, then resolve is returned; else, returns reject.

What is the return type of promise?

Returns a new Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise, the returned promise will be fulfilled with the value.

How do I return a value from promise TypeScript?

To access the value of a promise in TypeScript, call the then() method on the promise, e.g. p. then(value => console. log(value)) . The then() method takes a function, which is passed the resolved value as a parameter.


1 Answers

since returning Promise< void > is becoming quite a common pattern for me

You can use a type assertion

initialiseApp( ): Promise< void >
{
    let promises: Promise< any >[ ] = [ ];

    promises.push( this.initLanguageStrings( ) );
    promises.push( this.initModelData( ) );
    promises.push( this.initUserInfo( ) );

    return Promise.all( promises ) as Promise<void>;
}

Note : when you use an assertion you are essentially lying to the compiler in this case. Be careful about bugs where the compiler thinks one thing and the runtime sees another.

return Promise.all( promises ).then( ( ) => { } );

This is the right way to do it. The runtime matches what the compiler has inferred. If you want a Promise<void> ... then make a Promise<void> which is what this code sample does.

like image 57
basarat Avatar answered Oct 18 '22 20:10

basarat