DEV Community

Discussion on: The Proper Way to Write Async Constructors in JavaScript

Collapse
 
dandv profile image
Dan Dascalescu

I've read the 5 drawbacks of Workaround #1, but I don't quite see how they apply to the code I'm proposing. async-await works, there's no chaining of Promises, yes we use an arrow function to preserve this (is that a big deal?), and the last two points are unclear.

Thread Thread
 
somedood profile image
Basti Ortiz • Edited

Ah, my apologies. I was not clear enough with my phrasing. What I meant is that the async IIFE you're proposing is semantically equivalent to the chained promises I presented in the article—just with some nice syntax. If we were to transform the async IIFE into their chained equivalent, then the points I made in Workaround #1 are still applicable—again, just with nicer syntax.

My main issue lies in the atypical semantics of returning Promise<this> (assuming such syntax exists) from the constructor. Normally, I expect that a class constructor returns an instance of that class. However, using async IIFEs (or chained promises otherwise) goes against this expectation since it does not return this but Promise<this> instead.

The deal breaker, then, is the fact that although this technique is allowed and correct in JavaScript, it is difficult to deny that it is unexpected unless documented. In my opinion, it is best to explicitly tell the user (through the type signature) that the function returns Promise<this> rather than relying on external documentation to know that the constructor produces Promise<this> rather than this.

This is exactly why I recommended static async functions: their type signature does not hide the fact that it returns Promise<this>. This is not the case for the constructor, which TypeScript assumes to (implicitly) return this, not Promise<this>.

Thread Thread
 
fractal profile image
Fractal

Even if it's typed as Awaited<ClassName>?

Thread Thread
 
somedood profile image
Basti Ortiz

As far as I know, TypeScript does not allow the constructor to be directly type-annotated. As of writing, the compiler produces the following error:

Type annotation cannot appear on a constructor declaration.