Reputation: 100370
I have this method on an Angular service:
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]);
});
});
}
note that LastErrorType
is
export type LastErrorType = typeof chrome.runtime.lastError;
here is the problem, sometimes I pass a key, and I know the "return" type will be an array, for example:
getAllRunHistory() {
return this.cds.getFromSyncStorage('my-special-key');
}
but if I do this:
getAllRunHistory() : Promise<Array<any>>{
return this.cds.getFromSyncStorage('my-special-key');
}
tsc will complain and say that the return type is not assignable to Promise<Array<any>>
.
how can I use generics, so that this general-purpose getFromSyncStorage
method can be typed properly?
Upvotes: 0
Views: 333
Reputation: 100370
Looks like generics is the right thing to use. We change the original method to this:
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]);
});
});
}
then we use it like so:
this.getFromLocalStorage<Array<MyType>>(mds.key).then(...)
one caveat though, I don't really know how to specify the error type for the promise, which sucks, but I think it's a deficiency with the Promise TypeScript typings :(
Upvotes: 0
Reputation: 330161
You can do this with generics. Create a type representing the mapping from key to value type. In your case, it's something like:
type SyncStorageMap = {
"my-special-key": Array<any>,
[k: string]: Object // everything else
}
Then, type your method like this:
getFromSyncStorage<K extends keyof SyncStorageMap>(
key: K
): Promise<SyncStorageMap[K] | LastErrorType> {
// impl
}
Note that you might have to use type assertions in the implementation of that method if the compiler can't verify that "my-special-key"
corresponds to Array<any>
.
Then this code:
getAllRunHistory() {
return this.cds.getFromSyncStorage('my-special-key');
}
will be known to return Promise<Array<any> | LastErrorType>
. That's probably what you want unless you're sure that you will not get a LastErrorType
, in which case you can do something like this instead:
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
}
Hope that helps; good luck!
Upvotes: 1