0

我在 Angular 服务上有这个方法:

 getFromSyncStorage(key: string): Promise<Object | LastErrorType> {
    return new Promise(function (resolve, reject) {
      chrome.storage.sync.get(key, function (v: Object) {
        if (chrome.runtime.lastError) {
          return reject(chrome.runtime.lastError);
        }
        resolve(v && v[key]);
      });
    });
  }

请注意,这LastErrorType

export type LastErrorType = typeof chrome.runtime.lastError;

这就是问题所在,有时我传递一个键,我知道“返回”类型将是一个数组,例如:

getAllRunHistory() {
    return this.cds.getFromSyncStorage('my-special-key');
}

但如果我这样做:

getAllRunHistory() : Promise<Array<any>>{
    return this.cds.getFromSyncStorage('my-special-key');
}

tsc 会抱怨并说返回类型不可分配给Promise<Array<any>>.

如何使用泛型,以便getFromSyncStorage可以正确键入此通用方法?

4

2 回答 2

1

您可以使用泛型来做到这一点。创建一个表示从键到值类型的映射的类型。在您的情况下,它类似于:

type SyncStorageMap = {
    "my-special-key": Array<any>,
    [k: string]: Object // everything else
}

然后,像这样键入您的方法:

getFromSyncStorage<K extends keyof SyncStorageMap>(
  key: K
): Promise<SyncStorageMap[K] | LastErrorType> {
   // impl
}

请注意,如果编译器无法验证"my-special-key"对应于Array<any>.

然后这段代码:

getAllRunHistory() {
    return this.cds.getFromSyncStorage('my-special-key');
}

将知归来Promise<Array<any> | LastErrorType>。这可能就是你想要的,除非你确定你不会得到 a LastErrorType,在这种情况下你可以做这样的事情:

type SyncStorageMap = {
    "my-special-key": Array<any>, // no error
    [k: string]: Object | LastErrorType // maybe error
}

getFromSyncStorage<K extends keyof SyncStorageMap>(
  key: K
): Promise<SyncStorageMap[K]> {
   // impl
}

希望有帮助;祝你好运!

于 2018-02-23T19:29:43.407 回答
0

看起来泛型是正确的使用方法。我们把原来的方法改成这样:

 getFromSyncStorage<T>(key: string): Promise<T> {
    return new Promise(function (resolve, reject) {
      chrome.storage.sync.get(key, function (v) {
        if (chrome.runtime.lastError) {
          return reject(chrome.runtime.lastError);
        }
        resolve(v && v[key]);
      });
    });
  }

然后我们像这样使用它:

this.getFromLocalStorage<Array<MyType>>(mds.key).then(...)

不过需要注意的是,我真的不知道如何为 Promise 指定错误类型,这很糟糕,但我认为这是 Promise TypeScript 类型的缺陷:(

于 2018-02-24T00:51:50.710 回答