4

I am using VS Code and it helps a lot when working with Typescript as it tells you when current issues there are without needing to transpile. I am using Typescript with nodeJS and it works really well.

The only issue I have is so called "null / undefined checking functions".

See this example:

class User {
   public someProperty: string | undefined;
   // ...

   public get canDoSomething() {
      return this.someProperty != undefined;
   }
}
let myUser: User = ...

This works nicely:

if (myUser.someProperty != undefined) {
   // at this point myUser.someProperty is type string only (as it cannot be undefined anymore
}

However this fails

if (myUser.canDoSomething) {
   // because typescript still thinks that myUser.someProperty is string | undefined and not just string, even though this method checks for that.
}

Any idea how I would tell typescript? Because sometimes a method like that is cleaner than keep comparing the properties to undefined itself.

Thanks

4
  • Shouldn't the last if statement be: if (myUser.canDoSomething())? Without the parentheses, you're not invoking the type guard, just checking whether the function is defined or not. From TypeScript's perspective, someProperty can still be undefined. Commented Jun 27, 2019 at 14:09
  • 2
    @MehmetSeckin no, it a class property, not a method, notice the get Commented Jun 27, 2019 at 14:10
  • Ah, right, my bad. I just realised it was a class property. Commented Jun 27, 2019 at 14:11
  • You can use isNullOrUndefined(value) Commented Jun 27, 2019 at 14:30

2 Answers 2

6

Type narrowing works with specific syntactic constructs. if (obj.prop != undefined) is one such construct, that will inform the compiler prop can't be undefined.

In your case you perform the check in a property. Typescript will not follow the implementation of the getter to see that it performs the null check.

You could use a custom type guard (a method/function with special syntax that informs the compiler of type side effects) :

class User {
   public someProperty: string | undefined;

   public canDoSomething() : this is this & { someProperty: string} {
      return this.someProperty != undefined;
   }
}
let myUser: User = new User

if (myUser.canDoSomething()) {
    myUser.someProperty.big()
}

I would recommend with sticking with the simpler if (myUser.someProperty != undefined) though unless you have a good reason to encapsulate the check.

Edit

this is this & { someProperty: string} informs the compiler that the type of the object this method was invoked on (this) has now changed (is) to a new type (the intersection this & { someProperty: string}).

this in the intersection this & { someProperty: string} acts as the type for the current class (called polymorphic this) and will be either User or any class that derives from user (could have used User instead of this but it would not have worked on derived classes.

The intersection (&) with { someProperty: string} will mean that the type after the check is both whatever class we had before (this) and an object with a property someProperty of type string. Since User already had someProperty the type of someProperty in this intersection will work out to User['someProperty'] & string = (string | undefined) & string = stringefectively removing undefined from the type of someProperty in the resulting type.

Sign up to request clarification or add additional context in comments.

1 Comment

@MuratKaragöz I added an explanation, hope it makes things a bit more clear
-1

You might want to changed:

myUser.someProperty != undefined

To

typeof myUser.someProperty !== "undefined"

This will check the typing instead of the value.

2 Comments

The myUser.someProperty != undefined is the one that works ..the second one does not work
Doesn't really matter. If a variable is of type undefined, the variable will have the primitive value undefined. Modern browsers will not allow you to overwrite the undefined-type. But propertyName !== undefined is shorter than the typeof ...-check, so I'd prefer that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.