5

I'm using Typescript with es2017 as the compilation target, using Javascript's new async / await.

I currently have the following code to fetch some data from a TS service class (simplified):

class MyClass {

    public static async initialize(): Promise<void> {
        const data = await this.getItems();
        // do unrelated initialization stuff
        return new Promise<void>(() => {});
    }

    private static async getItems(): Promise<Item[]> {
        return await Service.fetchData();
    }
}

class Service {
    public static async fetchData(): Promise<Item[]> {
        // Performs an XHR and returns a Promise.
    }
}

This works, but it would be a lot cleaner if MyClass::initialize() did not return anything, rather than returning new Promise<void>(() => {}); However, this seems to be impossible, as any method/function that uses await has to be marked async, and any method/function that is marked as async has to return a promise.

Is there any way around this, or is there something I'm fundamentally not grasping?

Niek
  • 1,464
  • 1
  • 17
  • 27
  • "has to return a promise" does not apply to js. JavaScript `async` functions return a promise automatically, The function's return value (not necessarily a promise) resolves the promise returned when calling the function. Is Typescript different? – traktor Dec 30 '17 at 22:57
  • You should not write a `class` that has only static methods. Use an object literal instead. – Bergi Dec 30 '17 at 23:39
  • Have a look at [`toVoid` from my answer here](https://stackoverflow.com/a/40240420/1048572) – Bergi Dec 30 '17 at 23:42
  • @Bergi why is that? – Niek Dec 31 '17 at 13:48
  • 1
    @Niek A `class` should only be used for when objects need to be instantiated. It's inefficient (and confusing) otherwise. Object literals are just simpler. – Bergi Dec 31 '17 at 15:27

1 Answers1

7

Async functions in TypeScript do need to be declared to return promises, but you don't actually need to return a promise from the function. You can just return the type of the promise value from the async function and it will be taken care of that it is wrapped in a promise.

So, for async functions that return a Promise<void>, you can just have an empty return or no return at all.

class Item
{
}

class MyClass 
{

    public static async VoidAsyncWithReturn(): Promise<void>
    {
        return;
    }

    public static async VoidAsyncWithoutReturn(): Promise<void>
    {
    }

    private static async AsyncReturningValue(): Promise<Item[]> 
    {
        var result: Item[] = new Array();
        return result;
    }

    private static async AsyncReturningPromise(): Promise<Item[]> 
    {
        var result: Promise<Item[]> = new Promise<Item[]>(() => { return new Array() });
        return result;
    }
}
NineBerry
  • 26,306
  • 3
  • 62
  • 93
  • This gives me the error `The return type of an async function or method must be the global Promise type` in both the `MyClass::getItems()` and the `Service::fetchData()` methods. – Niek Dec 31 '17 at 13:47
  • 1
    @Niek Sorry, I got mixed up. I have corrected the answer. – NineBerry Dec 31 '17 at 17:12