类型在其自己的“ then”方法的实现回调中直接或间接引用

时间:2019-01-21 23:22:08

标签: typescript

使用Google Auth2 API的键入错误-@types/gapi.auth2。如果我创建使用1062类型解析的承诺,则编译器将引发错误gapi.auth2.GoogleAuth

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

打字有一个小怪癖:

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;
    ...
}

正在使用的代码是这样的:

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

只要有GoogleAuth类型,promise范围内的任何内容都没关系-这很令人沮丧。

问题肯定与类型有关,创建包装器或完全忽略错误可能很容易。 GoogleAuth对象是“可扩展的”,但是为什么会引起任何问题呢?有圆形参考书吗?

更麻烦的是1062错误很少。我尚未求助于阅读编译器代码,但到目前为止,我仍无法弄清它试图告诉我什么。

4 个答案:

答案 0 :(得分:2)

编辑:回答我自己的问题。

Google的文档明确指出:

警告:请勿调用Promise.resolve()和类似的结果 gapi.auth2.init()。返回的GoogleAuth对象将实现then() 自行解决的方法,将创建无限递归。

这意味着无论我们使用的是Typescript还是普通的Javascript,都会有麻烦。

因此,这里的Typescript保护用户免受无限递归的侵害。我不知道那是不是故意的。该措辞似乎表明它的问题完全是打字问题或编译器的限制。但实际上,它正在做重要的工作。

TL; DR:承诺结果是另一个返回自身的承诺。编译器错误正在防止无限递归。

答案 1 :(得分:2)

这是我发现规避此错误的方法

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

然后我可以这样做:

await this.loadGapiAuth();
const auth = gapi.auth2.getAuthInstance();

答案 2 :(得分:1)

您只需要从类型中省略then

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

  });
}

答案 3 :(得分:1)

通过自己的then()方法将Promise与任何对象一起使用是危险的。请参阅@gwilz答案。您将陷入无限循环!

一种解决方法是实际删除then()方法:

async function getGapi() {
  return new Promise<Omit<gapi.auth2.GoogleAuth, "then">>(resolve => {
    ...get auth object...
    delete auth.then;
    resolve(auth);
  });
}