Lehks
Lehks

Reputation: 3166

Typescript return if value is undefined

In TypeScript, is it possible to return whether a value is defined (i.e. not undefined) in such a way, that the transpiler understands that it is not undefined?

To clarify my question, image this example:

let myVar: MyClass | undefined = /*something*/

if(myVar) {
    myVar.foo() // this always works, because the transpiler knows that myVar will never be undefined
}

However, imagine that myVar needs to be initialized before foo() can be called. So the if statement becomes if(myVar && myVar.isInitialized()). But because this check needs to happen in a lot of functions, I wrote the function isUsable():

function isUsable(myVar: MyClass | undefined): boolean {
    return myVar && myVar.isInitialized();
}

let myVar: MyClass | undefined = /*something*/

if(isUsable(myVar)) {
    myVar.foo() // this does not work, because myVar may be undefined. I would have to use myVar?.foo() or myVar!.foo() which I want to avoid
}

Is it possible to define isUsable() in such a way, that the transpiler still understands, that myVar can not be undefined in the if-Block?

Upvotes: 1

Views: 1057

Answers (1)

satanTime
satanTime

Reputation: 13539

you need a type guard, myVar is MyClass.

function isUsable(myVar: MyClass | undefined): myVar is MyClass {
    return myVar && myVar.isInitialized();
}

let myVar: MyClass | undefined;

if(isUsable(myVar)) {
    myVar.foo(); // now it works.
}

since TS 3.7 you can even assert it.

function isUsable(myVar: MyClass | undefined): asserts myVar is MyClass {
  if (!myVar || !myVar.isInitialized()) {
    throw new Error();
  }
}

let myVar: MyClass | undefined;

isUsable(myVar);
myVar.foo(); // now it works.

Upvotes: 2

Related Questions