Search code examples
typescripttypespredicate

Using type predicates in class methods in TypeScript


I have a class defined like this

class Foo {
   value: string | null;
   constructor(){
      this.value = null;
   }
   private ensureValueExists():this.value is string{ //type predicate is not legal
      this.value = "bar";
      return true;
   }
   doStuffWithValue(){
      this.ensureValueExists();
      return 5 + this.value;  //ERROR, this.value can be null
   }
} 

I would like for the ensureValueExists method to be able to tell to the compiler that this.value is indeed a string and safe to use. Is there a special syntax to use or is it no doable with TS at the moment for methods ?


Solution

  • You can use an assertion method which narrows this. Support for that isn't particularly clear from the documentation, although a commit associated with microsoft/TypeScript#32695, the PR implementing assertion functions, demonstrates that it's possible.

    So in your case it would look like:

      private ensureValueExists(): asserts this is { value: string } {
        this.value = "bar";
      }
    

    (Note that you can't return anything in an assertion function/method), and then the following works:

      doStuffWithValue() {
        this.ensureValueExists();
        return 5 + this.value;  // okay
      }
    }
    

    There are definitely caveats associated with assertion functions and methods, but since you're only operating on this, you aren't running into them here.

    Playground link to code