TypeScript is giving me a type 'never' after a Promise.allSettled(promises).forEach(results)?
type myValue = {
test1: string;
test2: string;
test3: string;
} | undefined;
const go = async () => {
// the values
let value: myValue = undefined;
let value2: myValue = undefined;
// do some async requests
const results = await Promise.allSettled([
Promise.resolve({test1: 'test1.1', test2: 'test2.1', test3: 'test3.1'}),
Promise.resolve({test1: 'test1.2', test2: 'test2.2', test3: 'test3.2'}),
]);
// process results
results.forEach( (result, index) => {
if( result.status === "fulfilled") {
if( index === 0 ) {
// set value
value = result.value;
}
if( index === 1 ) {
// set value
value2 = result.value;
}
}
if( result.status === "rejected") {
// process error
console.error("error", result.reason);
}
});
// checking if value is set
if( !value || !value2 ) {
throw new Error("no Value found");
}
// with TypeScript errors
console.log("the type given is 'never', but value.test1 is set:", value.test1);
console.log("the type given is 'never', but value2.test3 is set:", value2.test3);
}
go();
TS playground: Visit
I have tried:
Why is TypeScript not inferring the type here?
Internally, TypeScript "stores" the value of value
and value2
to be undefined
, even though the type is MyValue
. Since TypeScript thinks it's undefined
and you don't reassign it in that scope TypeScript still thinks it's undefined when you perform the check !value || !value2
. Because TypeScript thinks it's undefined, it deduces that this condition will always be true and thus value
and value2
below can "never
" run. At least, that's what the compiler thinks.
Yes, you do actually reassign the values later, but the compiler just can't see that yet.
You actually have a very easy way to fix it - just remove the explicit initial value of undefined
:
let value: MyValue;
let value2: MyValue;