I have some code where I have several functions that need to null check an object then do stuff with it, or throw an error if it's null, like so:
interface SomeObject {
doThingOne: () => string;
doThingTwo: () => string;
}
let object: SomeObject | null;
function doThingOne() {
if(!object) {
throw new Error('Object is null!');
}
// Typescript knows that object is not null, so it's fine with accessing its properties/methods
return object.doThingOne();
}
function doThingTwo() {
if(!object) {
throw new Error('Object is null!');
}
return object.doThingTwo();
}
I'd like to pull out the null check into a function to reduce the duplicated code, like so:
interface SomeObject {
doThingOne: () => string;
doThingTwo: () => string;
}
let object: SomeObject | null;
function requireObject() {
if(!object) {
throw new Error('Object is null!');
}
}
function doThingOne() {
requireObject();
// Typescript no longer knows that object is defined, so it gets mad at the next line
return object.doThingOne();
}
function doThingTwo() {
requireObject();
return object.doThingTwo();
}
However, when I do so, typescript is no longer aware that after the check, object definitely exists. Is there a clean way to do this?
This question seems similar, but wouldn't actually let me save on much code repetition as I'd still need to set up an if
object, if it exists, is of a type that has some methods on it. The issue's the same regardless of if I want to callobject.doThingOne()or useobject.someProperty.requireObject()affect the state of arbitrary in-scope values. You can an assertion function to get similar results but you need to pass in the guarded thing as an argument, likerequireObject(object). See here. If this approach meets your needs I can write up an answer, otherwise the answer is basically "no, you can't do this" which I could write up as an answer, I suppose, maybe. Let me know.