Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can a function check for null in typescript?

in typescript 2.6 I want to write a function that does a null check. When I enable strict null-checks, typescript 2.6 complains about the following code. (Note that when using the null check directly works)

edited: corrected notNullOrUndefined since it didn't check for foo

interface A {
  foo: string | undefined;
}
const notNullOrUndefined = (a: A): boolean => {
  return a.foo != null;
}
const len = (a: A): number => {
  //if (a.foo != null) {
  if (notNullOrUndefined(a)){
    return a.foo.length;
  }
  return 0;
} 

here is the example to play with: example

What's the typescript way to solve this?

like image 580
oliver Avatar asked Nov 08 '25 09:11

oliver


1 Answers

EDIT: updated to reflect fixing a typo in question: The question is a little confusing, since your notNullOrUndefined() doesn't check a.foo at all, so it's not surprising that those would be different.

Note that with --strictNullChecks on, you have defined len() so that the a parameter is an A, and therefore cannot be null or undefined. So you don't have to check a itself inside the len() function implementation; instead you need to make sure that anything you pass to len() is a valid A. So notNullOrUndefined() is kind of a bad name, since you're checking the foo value of the parameter, not the parameter itself. Feel free to change it to something like fooPropertyIsNotNull(); I will leave it for now.

The main issue here is that TypeScript recognizes that if (a.foo != null) { ... } is a type guard, and narrows a.foo to string inside the { ... } clause. But type guards do not propagate out of functions automatically, so TypeScript doesn't understand that notNullOrUndefined() itself acts as a type guard.

Luckily, this issue is common enough that TypeScript provides user-defined type guards: if you have a function that returns a boolean which narrows the type of one of its parameters, you can change the boolean return type to a type predicate, using the x is T syntax. Here it is for notNullOrUndefined():

const notNullOrUndefined = (a: A): a is { foo: string } => {
  return a.foo != null;
}

So the function signature says: if you pass in an A, it will return a boolean value. If it returns true, then the passed-in parameter is narrowed to { foo: string }. Now you will get no errors, as you wanted:

interface A {
  foo: string | undefined;
}
const notNullOrUndefined = (a: A): a is { foo: string } => {
  return a.foo != null; // checking a.foo
}
const len = (a: A): number => {
  if (notNullOrUndefined(a)){
    return a.foo.length; // okay
  }
  return 0;
} 

Hope that helps, good luck!

like image 106
jcalz Avatar answered Nov 10 '25 01:11

jcalz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!