Having the following code:
function A(arg1?: string, arg2?: number) {
if (!arg1 && !arg2) {
throw new Error('At least one of two parameters must be present');
}
B(arg1 || arg2);
}
function B(arg3: string | number) {
// does something. we don't really care
}
Typescript throws the following compilation error for the expression B(arg1 || arg2)
:
Argument of type 'string | number | undefined' is not assignable to parameter of type 'string | number'.
Type 'undefined' is not assignable to type 'string | number'. ts(2345)
However, in function A I make sure that at least one of the arguments is not undefined, throwing an error in that case. That means that in the expression B(arg1 || arg2)
the argument will never be undefined, it will always be either number or string.
Is something wrong in my assumption? Is there any way of making typescript understand it?
If you were doing a truthy check on a single value TS would indeed correctly infer that the value is no longer undefined
if (arg1) {
arg1; // arg1: string
}
When you check two variables though, TS doesn't know for certain that either of them individually are truthy, so arg1
and arg2
are still string | undefined
and number | undefined
respectively.
One option is to assign arg1 || arg2
to a variable before the if statement so the truthy inference works correctly.
function A(arg1?: string, arg2?: number) {
const arg = arg1 || arg2; // arg: string | number | undefined
if (arg) {
// arg: string | number
B(arg);
} else {
throw new Error('At least one of two parameters must be present');
}
}
function B(arg3: string | number) {
// does something. we don't really care
}
A new !
post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact.
What's new
If you sure that at least one of args is not undefined
, you could use !
syntax like this:
function A(arg1?: string, arg2?: number) {
if (!arg1 && !arg2) {
throw new Error('At least one of two parameters must be present');
}
B(arg1! || arg2!); // In compile time `arg1` and `arg2` are not `undefined`, in runtime maybe, but you sure the case never come true :)
}
function B(arg3: string | number) {
// does something. we don't really care
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With