Safe navigation operator (?.) or (!.) and null property paths

In Angular 2 templates safe operator ?. works, but not in component.ts using TypeScript 2.0. Also, safe navigation operator (!.) doesn't work.

For example:

This TypeScript

if (a!.b!.c) { }

compiles to this JavaScript

if (a.b.c) { }

But when I run it, I get the follow error:

Cannot read property 'b' of undefined

Is there any alternative to the following?

if (a && a.b && a.b.c) { }

! is non-null assertion operator (post-fix expression) - it just saying to type checker that you're sure that a is not null or undefined.

the operation a! produces a value of the type of a with null and undefined excluded


Optional chaining finally made it to typescript (3.7) 🎉

The optional chaining operator ?. permits reading the value of a property located deep within a chain of connected objects without having to expressly validate that each reference in the chain is valid. The ?. operator functions similarly to the . chaining operator, except that instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined. When used with function calls, it returns undefined if the given function does not exist.

Syntax:

obj?.prop // Accessing object's property
obj?.[expr] // Optional chaining with expressions
arr?.[index] // Array item access with optional chaining
func?.(args) // Optional chaining with function calls

Pay attention:

Optional chaining is not valid on the left-hand side of an assignment

const object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment

Since TypeScript 3.7 was released you can use optional chaining now.

Property example:

let x = foo?.bar.baz();

This is equvalent to:

let x = (foo === null || foo === undefined)
  ? undefined
  : foo.bar.baz();

Moreover you can call:

Optional Call

function(otherFn: (par: string) => void) {
   otherFn?.("some value");
}

otherFn will be called only if otherFn won't be equal to null or undefined

Usage optional chaining in IF statement

This:

if (someObj && someObj.someProperty) {
  // ...
}

can be replaced now with this

if (someObj?.someProperty) {
  // ...
}

Ref: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html


Update:

Planned in the scope of 3.7 release
https://github.com/microsoft/TypeScript/issues/33352


You can try to write a custom function like that.

The main advantage of the approach is a type-checking and partial intellisense.

export function nullSafe<T, 
    K0 extends keyof T, 
    K1 extends keyof T[K0],
    K2 extends keyof T[K0][K1],
    K3 extends keyof T[K0][K1][K2],
    K4 extends keyof T[K0][K1][K2][K3],
    K5 extends keyof T[K0][K1][K2][K3][K4]>
    (obj: T, k0: K0, k1?: K1, k2?: K2, k3?: K3, k4?: K4, k5?: K5) {
    let result: any = obj;

    const keysCount = arguments.length - 1;
    for (var i = 1; i <= keysCount; i++) {
        if (result === null || result === undefined) return result;
        result = result[arguments[i]];
    }

    return result;
}

And usage (supports up to 5 parameters and can be extended):

nullSafe(a, 'b', 'c');

Example on playground.