Typescript check variable null or undefined

Viewed 5900

Sorry not sure how to describe my question. Hope the title does not mislead you.

First of all, my issue happens in Angular 11 with strict mode turned on.

Suppose I have an array

let results: T[] = [];

and I have a function as follow and this function does not give any error in Visual Studio Code.

filter = (values: (T | null | undefined)[]): T[] => {
  for(let value of values) {
    if (value !== null && value !== undefined) {
      results.push(value);
    }
  }
}

However, if I extract the condition to another function, such as

isNullOrUndefined = (value: T | null | undefined): bool => {
  return value === null || value === undefined;
}

and then use the function in the above filter function as follow:

filter = (values: (T | null | undefined)[]): T[] => {
  for(let value of values) {
    if (!isNullOrUndefined(value)) {
      results.push(value);
    }
  }
}

I get an error Argument of type 'Nullable<T>' is not assignable to parameter of type 'T'.

Can anyone please help to have a look? Thank you

1 Answers

The problem is with the typing of the isNullOrUndefined function.

When you use the condition like this

if (value !== null && value !== undefined) {
     results.push(value); // value is only T here

it is used as a type constrain. Typescript automatically constrains the type of value in the if branch to T.

But if you use isNullOrUndefined which returns boolean, Typescript does not check the actual implementation of the function - even if you did not specify the return type explicitly.

if (!isNullOrUndefined(value)) {
  results.push(value); // value still is T | null | undefined
}

In order to make it work, you need to type the isNullOrUndefined as a type contrain as well by specifying the return type as value is null | undefined

isNullOrUndefined = (value: T | null | undefined): value is null | undefined => {
  return value === null || value === undefined;
}

Then Typescript will behave the same as with the original version.

if (!isNullOrUndefined(value)) {
  results.push(value); // value is T
}
Related