sebbab
sebbab

Reputation: 1046

Removing null check using if statement in typescript

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

Answers (2)

Aron
Aron

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

hoangdv
hoangdv

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.

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
}

Upvotes: 2

Related Questions