使用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错误很少。我尚未求助于阅读编译器代码,但到目前为止,我仍无法弄清它试图告诉我什么。
答案 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);
});
}