Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type is referenced directly or indirectly in the fulfillment callback of its own 'then' method

Tags:

typescript

An errors blows up when using the typings for the the Google Auth2 API - @types/gapi.auth2. The compiler throws an error 1062 if I create a promise that resolves with the gapi.auth2.GoogleAuth type.

Type is referenced directly or indirectly in the fulfillment callback of its own 'then' method.

The typings have this little quirk:

class GoogleAuth {
    ...
    /**
     * Calls the onInit function when the GoogleAuth object is fully initialized, or calls the onFailure function if
     * initialization fails.
     */
    then(onInit: (googleAuth: GoogleAuth) => any, onFailure?: (reason: {error: string, details: string}) => any): any;
    ...
}

The code in use is something like this:

async function getGapi() {
    return new Promise<gapi.auth2.GoogleAuth>(resolve => {
        ...
    });
}

It doesn't matter whatever is inside the promise scope, as soon as it has that GoogleAuth type - it's upset.

The problem is definitely related to the typings and it's probably easy to create a wrapper or ignore the error entirely. The GoogleAuth object is 'thennable' but why should that cause any problem? Is there a circular reference or something?

What's more troubling is there is very little on the 1062 error. I haven't yet resorted to reading the compiler code, but so far I can't figure out what it's trying to tell me.

like image 653
gwillz Avatar asked Jan 21 '19 23:01

gwillz


3 Answers

Edit: Answering my own question.

Google's documentation explicity says this:

Warning: do not call Promise.resolve() and similar with the result of gapi.auth2.init(). As the GoogleAuth object returned implements the then() method that resolves with itself, it will create an infinite recursion.

This means there will be trouble whether we're using Typescript or even plain Javascript.

So here Typescript is protecting the user from an infinite recursion. Whether or not that is it's intention, I don't know. The wording seems to suggest it's issue is entirely a typing problem or limitation of the compiler. But it's actually doing an important job.

TL;DR: The promise result is another promise which returns itself. The compiler error is guarding against infinite recursions.

like image 108
gwillz Avatar answered Oct 19 '22 02:10

gwillz


You just need to omit then from the type.

async function getGapi() {
  return new Promise<Omit<gapi.auth2.GoogleAuth, "then">>(resolve => {

  });
}
like image 44
Blake Bowen Avatar answered Oct 19 '22 03:10

Blake Bowen


This is the way I found to circumvent this error

private async loadGapiAuth() {
  await new Promise((resolve) => gapi.load('client:auth2', resolve));
  await new Promise((resolve) => gapi.auth2.init(GAPI_CONFIG).then(resolve));
}

then I can do this:

await this.loadGapiAuth();
const auth = gapi.auth2.getAuthInstance();
like image 3
Estevão Lucas Avatar answered Oct 19 '22 02:10

Estevão Lucas