In Typescript I am checking if an object\'s properties are null as follows:
var addressCountryName = response.address == null
? null
: response.addre
As others have mentioned the null coalescing operator
is still in a proposal stage so you can't access properties using ?.
Your only options currently are to do deep nesting with if statements or ternarys or to consider something like the get
method from lodash which would let you do:
let addressCountryName = get(response, 'address.country.name');
Which will either return the value of name or undefined if any part of the object path was null or undefined.
Here's a CodeSandbox with an example of using lodash: https://codesandbox.io/s/mm46wkr058
! is the non-null assertion operator in Typescript. ? is for Angular html templates.
There is currently no null coalescing operator in JavaScript. There are different ways to get around it (like your nested ternary types). If you're willing to shove helper types and functions into a library somewhere, you could do this:
type MyResponse = {
address?: null | {
country?: null | {
name?: null | string
}
}
}
let response: MyResponse = Math.random() < 0.5 ?
{ address: { country: { name: "France" } } } : { address: null }
var addressCountryName = nullSafe(response, r => r.address.country.name);
// string | undefined | null
Where nullSafe()
is defined like this:
interface NullSigil {
[k: string]: NullSigil;
}
// phantom property to recover T from NullSafe<T>
type OriginalTypeKey = "***originalType***"
type IsNullable<T, Y, N> = null extends T ? Y :
undefined extends T ? Y : N;
type NullSafe<T, N = NullSigil> = Record<OriginalTypeKey, T> & (
T extends object ? {
[K in keyof T]-?: NullSafe<T[K], N>
} : IsNullable<T, NonNullable<T> | N, T>
)
type NullUnsafe<T> =
T extends Record<OriginalTypeKey, infer U> ? U :
T extends NullSigil ? null :
T
function nullSafe<T, U>(
val: T,
fn: <N extends NullSigil>(nullSafeVal: NullSafe<T, N>) => U
): NullUnsafe<U>;
function nullSafe(val: any, fn: (nullSafeVal: any) => any): any {
const nullSigil: NullSigil = new Proxy({} as NullSigil, { get(t, p, r) { return r } });
const deproxify = Symbol("deproxify");
function ns<T>(obj: T): NullSafe<T>;
function ns(obj: any) {
if ((typeof obj === "undefined") || (obj === null)) return nullSigil;
if (typeof obj !== "object") return obj;
return new Proxy(obj, { get(t, p, r) { return (p === deproxify) ? t : (p in t) ? ns(t[p]) : nullSigil } });
}
const ret: any = fn(ns(val));
if (ret === nullSigil) return null;
if (typeof ret !== "object") return ret;
return ret[deproxify];
}
Yes, it's a mess, that's why I said to shove it into a library. It works by making a Proxy that always allows you to drill down into properties even if it is essentially null.
Anyway, it's one option. Good luck!