Currently working on creating a function that can gracefully handle unexpected "failures". My initial thought was to go with a go-style function return, typing the return as [Val, null] | [null, Error]
.
However, I encountered an issue when trying to type-guard the return value with an if statement,
const [val, err] = myFunc(); // => [Val, null] | [null, Error]
if (err) {
handle(err);
return;
}
// At this point, the return value must be of type [Val, null]
doSomethingWith(val) // Error! Type 'null' is not assignable to type 'Val'
This scenario is causing confusion because a similar approach with objects works without any issues, (Link to playground)
const res = myFunc(); // => {type: 'Error'} | {type: 'Success', data: Val}
if (res.type === 'Error') {
handle(res);
return;
}
// In this case, res is correctly narrowed down to {type: 'Success', data: Val}
doSomethingWith(res.data)
It appears that the union of tuples is being transformed into a tuple of unions,
from [Val, null] | [null, Error]
to [Val | null, null | Error]
Is this the expected behavior? What is the reason behind this, and is there a way to work around it?