Given two promises - one that needs to be executed every time and one that needs to be executed only if a condition is met - that I want to execute asynchronously, how do I ensure that return type of Promise.all
for each value is correct?
Here's an implementation that I thought should work:
type Promises = [Promise<string>, Promise<number>?]
const promises: Promises = [Promise.resolve('Lorem')]
if (someCondition) {
promises.push(Promise.resolve(1))
}
// 'resolvedString' should be string
// 'resolvedNumber' should be number | undefined
const [resolvedString, resolvedNumber] = await Promise.all(promises)
but there are two issues with this code:
Value of
resolvedNumber
isnumber
and notnumber | undefined
according to VSCodeTS doesn't compile because of following error:
The last overload gave the following error.
Argument of type 'Promises' is not assignable to parameter of type 'Iterable<string | PromiseLike<string>>'.
The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
Type 'IteratorResult<Promise<string> | Promise<number>, any>' is not assignable to type 'IteratorResult<string | PromiseLike<string>, any>'.
Type 'IteratorYieldResult<Promise<string> | Promise<number>>' is not assignable to type 'IteratorResult<string | PromiseLike<string>, any>'.
Type 'IteratorYieldResult<Promise<string> | Promise<number>>' is not assignable to type 'IteratorYieldResult<string | PromiseLike<string>>'.
Type 'Promise<string> | Promise<number>' is not assignable to type 'string | PromiseLike<string>'.
Type 'Promise<number>' is not assignable to type 'string | PromiseLike<string>'.
Type 'Promise<number>' is not assignable to type 'PromiseLike<string>'.
Types of property 'then' are incompatible.
Type '<TResult1 = number, TResult2 = never>(onfulfilled?: (value: number) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<...>' is not assignable to type '<TResult1 = string, TResult2 = never>(onfulfilled?: (value: string) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<...>'.
Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
Types of parameters 'value' and 'value' are incompatible.
Type 'number' is not assignable to type 'string'.
93 const [resolvedString, resolvedNumber] = await Promise.all(promises)
TypeScript version is 4.3.5
CodePudding user response:
I don't know if I get the problem right, but, you can basically set several types in your promise, I believe this could help?
Such a type would allow your array to contain several Promises of "different" types. You could eventually Promise.all on this entire array?
const promises: Promise<string | number>[] = [Promise.resolve('Lorem')]
if (someCondition) {
promises.push(Promise.resolve(1))
}
CodePudding user response:
This is a bug/feature that has been fixed on TS 4.5.