Allen
Allen

Reputation: 3374

Using strictNullChecks is there a way to assert non-null inline with code without if statement

I have recently enabled strictNullChecks our code. I would like to write an assertion helper that can be used inline for places where we should not have a null but the type still has null as a possible value.

Something like:

doSomething() {
    assertNonNull(this.obj);  // throws exception if null
    this.obj.doMore();
}

I know I could do this with a this.obj!.doMore() but I would like to have the runtime assertion to verify it and then have typescript know that past that assertion the type union does not contain null anymore.

Is it possible to write a helper function like this? So far I can't seem to come up with anything.

Upvotes: 1

Views: 373

Answers (2)

artem
artem

Reputation: 51769

You could make assertNonNull to return its argument, appropriately typed when it's non-null, or throw otherwise:

function assertNonNull<T>(x: T | null | undefined): T {
    if (x === null || x === undefined) {
        throw new Error('non-null assertion failed');
    } else {
        return x;
    }  
}

Then you can use it like this:

class Foo {

    obj: { doMore() } | null;

    doSomething() {
        assertNonNull(this.obj).doMore();
    }
}

Upvotes: 2

Nitzan Tomer
Nitzan Tomer

Reputation: 164397

No, that's currently not possible (as far as I'm aware), as the language has no support for error throwing.

What you can do is:

class MyClass {
    private obj: { doMore(): void } | null;

    doSomething() {
        if (assertNonNull(this.obj)) {
            this.obj.doMore(); // this.obj is not null here
        }
    }
}

function assertNonNull(obj: { doMore(): void } | null): obj is { doMore(): void } {
    return obj != null;
}

(code in playground)

Alternitvely you can do this instead:

doSomething() {
    if (!assertNonNull(this.obj)) {
        throw new Error("obj is null");
    }

    this.obj.doMore(); // this.obj is not null here
}

But you cannot have type guard based on throwing an error.
It should be possible if a feature I requested for will be added: throws clause and typed catch clause.

You can add your scenario to the issue, it shows another usage for it.

Upvotes: 2

Related Questions