Reputation: 976
I want to get values of Promise allSettled result in typescript code. In JavaScript this work well.
Promise.allSettled([
Promise.resolve(33),
new Promise(resolve => setTimeout(() => resolve(1000), 0)),
25000,
Promise.reject(new Error('failed!'))
])
.then(values => {
let allValues = values.filter(c=>c.status === 'fulfilled').map(v=>v.value);
console.log(allValues);
});
But in typescript I can't find correct syntax. the item just have status and has no value property. I am using the latest version of typescript 3.9.7
Upvotes: 4
Views: 6997
Reputation: 2730
Oh my, 3 y.o. question. Anyway, better late than never. =)
I would suggest to use a few helper type guards to actually filter fulfilled
and rejected
results.
const isFullfilled = <T>(
value: PromiseSettledResult<T>
): value is PromiseFulfilledResult<T> => {
return value.status === 'fulfilled'
}
const isRejected = <T>(
value: PromiseSettledResult<T>
): value is PromiseRejectedResult => {
return value.status === 'rejected'
}
const fetchNumbers = () => {
return Promise.allSettled([
Promise.resolve(33),
new Promise<number>((resolve) => setTimeout(() => resolve(1000), 0)),
25000,
Promise.reject(new Error('failed!')),
])
}
const main = async () => {
const responses = await fetchNumbers()
const doubledNumbers = responses
.filter(isFullfilled)
.map((response) => response.value * 2)
}
main()
As you can see there are 2 type guards which forces the filter
method to actually return a correct type either PromiseFulfilledResult
or PromiseRejectedResult
.
You can get more information about how the guards work right here: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types
Upvotes: 1
Reputation: 976
Ok I finally found the correct syntax for using Promise.allSettled in typescript:
Update: Thanks to @myol I updated the code without unnecessary map:
const dummyResolve1 = Promise.resolve(1000);
const dummyResolve2 = new Promise(resolve => setTimeout(() => resolve(2000), 0));
const dummyError = Promise.reject(new Error('failed'));
const dummyPromises = [dummyResolve1, dummyResolve1, dummyError];
Promise.allSettled(dummyPromises)
.then(results => {
const allValues = (results.filter(c=>c.status === 'fulfilled') as PromiseFulfilledResult<any>[])
.map(c=>c.value);
console.log(allValues);
const failedResults =
(results.filter(c=>c.status === 'rejected') as PromiseRejectedResult[])
.map(c=>c.reason);
console.log(failedResults);
});
Old code:
Promise.allSettled([
Promise.resolve(1000),
new Promise(resolve => setTimeout(() => resolve(2000), 0)),
1500,
Promise.reject(new Error('failed'))
])
.then(values => {
let allValues = values.filter(c=>c.status === 'fulfilled').map(c=> <PromiseFulfilledResult<any>>c).map(c=>c.value);
console.log(allValues);
let failedResults = values.filter(c=>c.status === 'rejected').map(c=> <PromiseRejectedResult>c).map(c=>c.reason);
console.log(failedResults);
});
Upvotes: 10
Reputation: 9828
I think you really want the following;
const fulfilledValues: any[] = (values as PromiseFulfilledResult<any>[])
.filter(res => res.status === 'fulfilled')
.map(res => res.value);
console.log(fulfilledValues);
const rejectedReasons: any[] = (values as PromiseRejectedResult[])
.filter(res => res.status === 'rejected')
.map(res => res.reason);
console.log(rejectedReasons);
No need for an extraneous JS .map
call just to use type assertion in TS.
Upvotes: 1