Reputation: 1046
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?
Upvotes: 4
Views: 2671
Reputation: 9238
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
}
Upvotes: 7
Reputation: 16127
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.
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
}
Upvotes: 2