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:
- comments: @ts-ignore / @ts-expect-error / etc but I don't want to do this, because I need a lot of them.
- typecasting: value = value as MyValue; will also make the error dissapear, but should not be needed here
Why is TypeScript not inferring the type here?
Internally, TypeScript "stores" the value of
valueandvalue2to beundefined, even though the type isMyValue. Since TypeScript thinks it'sundefinedand 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 thusvalueandvalue2below 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:Playground