Reputation: 3166
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
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