Reputation: 39484
In Typescript I am checking if an object's properties are null as follows:
var addressCountryName = response.address == null
? null
: response.address.country == null ? null : response.address.country.name;
Both addresses and country can be null ... I also tried:
var addressCountryName = response.address?.country?.name;
This does not seem to work ...
Is there a shortest way to check for null / undefined?
Upvotes: 5
Views: 11680
Reputation: 21207
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
Upvotes: 2
Reputation: 330086
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!
Upvotes: 4
Reputation: 1414
! is the non-null assertion operator in Typescript. ? is for Angular html templates.
Upvotes: 0