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

11,370

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.

Share:
11,370

Related videos on Youtube

Kevmeister68
Author by

Kevmeister68

Updated on June 04, 2022

Comments

  • Kevmeister68
    Kevmeister68 almost 2 years

    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.

  • Kevmeister68
    Kevmeister68 over 8 years
    The downside I see to using a cast (type assertion) is that not only are we lying to the compiler, but the result "bleeds out" of the function to the caller. In other words, the caller of initialiseApp will in fact receive the any[ ] from Promise.all even though the method says nothing should be returned.