Issue
I want to make a function that will try running provided function, and will throw unless it returns a truthy value, like this:
function test<T>(runnable: () => T): T {
const value = runnable();
if (! value) throw new Error(`Only truthy`);
return value;
}
const a = test(() => {
return (Math.random() < 0.5) ? undefined : "ok";
});
console.log(a);
How do I change the definition of test so that TS knows that a is always a string, not string|undefined?
Solution
If you make the falsy types part of inner function return type, but not part of the outer function type, then this is possible:
First, make a Falsy type alias:
type Falsy = false | null | undefined | 0 | ''
And now make a union with T for the inner function return type:
function test<T>(runnable: () => T | Falsy): T {
const value = runnable();
if (!value) throw new Error(`Only truthy`);
return value;
}
This means that T is inferred to not include the Falsy types. And the inner runnable function is allowed to return T or any Falsy type. Then you check for the Falsy type and proceed to the return only if the value is not a Falsy, which must be a T.
Now this function has a return type of "ok" since the error traps all other results.
const a = test(() => {
return (Math.random() < 0.5) ? undefined : "ok";
});
a // type: "ok"
Answered By - Alex Wayne
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.