Reputation: 1025
I have two async gets I'd like to call, the second which uses the output of the first one, and their returned types (within the Promise) are different.
These are from the AsyncStorage
library in React.
My code is:
function fetchAllSecretsRaw(): Promise<[string, string | null][]> {
return AsyncStorage.getAllKeys().then((allKeys) => {
return AsyncStorage.multiGet(allKeys.filter(isSecretKey));
});
}
I am surprised that this typechecks when looking at the Promise declaration. How does this work? How can Promise<[string, string | null][]>
satisfy Promise<string[]>
(which comes from TResult1 = T
?
The async functions signatures are:
getAllKeys(callback?: (error?: Error, keys?: string[]) => void): Promise<string[]>;
multiGet(
keys: string[],
callback?: (errors?: Error[], result?: [string, string | null][]) => void
): Promise<[string, string | null][]>;
while .then on a Promise<T>
is:
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
The first getAllKeys()
gives me a Promise<string[]>
, which according to the Promise declaration means that T=string[]
Since TResult1 = T
(from then's declaration then<TResult1 = T,
) does that mean TResult1 = string[]
?
But the onfulfilled
function I pass actually returns a Promise<[string, string | null][]>
, i.e. a tuple array instead of a string array.
Upvotes: 1
Views: 840
Reputation: 664538
the
.then
declaration also constrains thatTResult1 = T
No, it doesn't constrain it (like an extends
clause would) - that's only a default value for when no onfulfilled
callback is provided.
But you did provide one, and its type is (value: string[]) => Promise<[string, string | null][]>
, so TResult1
is properly inferred to [string, string | null][]
.
Upvotes: 1
Reputation: 19987
TResult1
is the type of the return value of the onfulfilled
function (in your case [string, string | null][]
) OR if onfulfilled
is absent the type of T
(in your case string[]
).
Since your onfulfilled
function is:
(allKeys) => {
return AsyncStorage.multiGet(allKeys.filter(isSecretKey));
}
which returns a Promise<[string, string | null][]>
. This therefore type checks fine. It is not a mistake.
Upvotes: 2