Typescript assert-like type guard Typescript assert-like type guard typescript typescript

Typescript assert-like type guard


Typescript 3.7 adds assertions in control flow analysis.

An asserts return type predicate indicates that the function returns only when the assertion holds and otherwise throws an exception

Hacks on consumer side are not needed anymore.

interface Foo { bar(): void }declare function getFoo(): Foo | undefined;function assert(value: unknown): asserts value {    if (value === undefined) {        throw new Error('value must be defined');    }}function test() {    const foo = getFoo();    // foo is Foo | undefined here    assert(foo);    // foo narrowed to Foo    foo.bar();}

Playground


Additionally one can assert that provided parameter is of required type:

declare function assertIsArrayOfStrings(obj: unknown): asserts obj is string[];function foo(x: unknown) {    assertIsArrayOfStrings(x);    return x[0].length;  // x has type string[] here}

Playground


There is an issue in the typescript backlog for this https://github.com/Microsoft/TypeScript/issues/8655. So for now you can't do this.

What you can do, is to use the assertion operator "!". Adding ! after value will assert that the value is neither undefined nor null. Use this is case where you're absolutely sure it cannot lead to a null or undefined reference.

function test() {     const foo: (FooType|null) = getFoo();     foo!.bar(); // "!" - asserts that foo is not null nor undefined}

Source: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-type-assertions


Since foo is Foo | undefined, its type should be changed to Foo somehow.

In the code above, this reasonably can be done with:

let foo = getFoo(); // Foo | undefinedfoo = assertResultDefined(foo); // Foofoo.bar();

Another option is to use non-null assertion (as another answer suggests):

let foo = getFoo();foo = assertResultDefined(foo);foo = foo!;foo.bar();