Since TypeScript is strongly-typed, simply using if () {}
to check for null
and undefined
doesn't sound right.
Does TypeScript have any dedicated function or syntax sugar for this?
Using a juggling-check, you can test both null
and undefined
in one hit:
if (x == null) {
If you use a strict-check, it will only be true for values set to null
and won't evaluate as true for undefined variables:
if (x === null) {
You can try this with various values using this example:
var a: number;
var b: number = null;
function check(x, name) {
if (x == null) {
console.log(name + ' == null');
}
if (x === null) {
console.log(name + ' === null');
}
if (typeof x === 'undefined') {
console.log(name + ' is undefined');
}
}
check(a, 'a');
check(b, 'b');
Output
"a == null"
"a is undefined"
"b == null"
"b === null"
In TypeScript 3.7 we have now Optional chaining and Nullish Coalescing to check null and undefined in the same time, example:
let x = foo?.bar.baz();
this code will check if foo is defined otherwise it will return undefined
old way :
if(foo != null && foo != undefined) {
x = foo.bar.baz();
}
this:
let x = (foo === null || foo === undefined) ? undefined : foo.bar();
if (foo && foo.bar && foo.bar.baz) { // ... }
With optional chaining will be:
let x = foo?.bar();
if (foo?.bar?.baz) { // ... }
another new feature is Nullish Coalescing, example:
let x = foo ?? bar(); // return foo if it's not null or undefined otherwise calculate bar
old way:
let x = (foo !== null && foo !== undefined) ?
foo :
bar();
I did different tests on the typescript playground:
http://www.typescriptlang.org/play/
let a;
let b = null;
let c = "";
var output = "";
if (a == null) output += "a is null or undefined\n";
if (b == null) output += "b is null or undefined\n";
if (c == null) output += "c is null or undefined\n";
if (a != null) output += "a is defined\n";
if (b != null) output += "b is defined\n";
if (c != null) output += "c is defined\n";
if (a) output += "a is defined (2nd method)\n";
if (b) output += "b is defined (2nd method)\n";
if (c) output += "c is defined (2nd method)\n";
console.log(output);
gives:
a is null or undefined
b is null or undefined
c is defined
so:
I think this answer needs an update, check the edit history for the old answer.
Basically, you have three deferent cases null, undefined, and undeclared, see the snippet below.
// bad-file.ts
console.log(message)
You'll get an error says that variable message
is undefined (aka undeclared), of course, the Typescript compiler shouldn't let you do that but REALLY nothing can prevent you.
// evil-file.ts
// @ts-gnore
console.log(message)
The compiler will be happy to just compile the code above. So, if you're sure that all variables are declared you can simply do that
if ( message != null ) {
// do something with the message
}
the code above will check for null
and undefined
, BUT in case the message
variable may be undeclared (for safety), you may consider the following code
if ( typeof(message) !== 'undefined' && message !== null ) {
// message variable is more than safe to be used.
}
Note: the order here typeof(message) !== 'undefined' && message !== null
is very important you have to check for the undefined
state first atherwise it will be just the same as message != null
, thanks @Jaider.
You may want to try
if(!!someValue)
with !!
.
Explanation
The first !
will turn your expression into a boolean
value.
Then !someValue
is true
if someValue
is falsy and false
if someValue
is truthy. This might be confusing.
By adding another !
, the expression is now true
if someValue
is truthy and false
if someValue
is falsy, which is much easier to manage.
Discussion
Now, why do I bother myself with if (!!someValue)
when something like if (someValue)
would have give me the same result?
Because !!someValue
is precisely a boolean expression, whereas someValue
could be absolutely anything. This kind of expression will now alow to write functions (and God we need those) like:
isSomeValueDefined(): boolean {
return !!someValue
}
instead of:
isSomeValueDefined(): boolean {
if(someValue) {
return true
}
return false
}
I hope it helps.
For Typescript 2.x.x
you should do it in a following way(using type guard):
tl;dr
function isDefined<T>(value: T | undefined | null): value is T {
return <T>value !== undefined && <T>value !== null;
}
Why?
In this way isDefined()
will respect variable's type and the following code would know take this check in account.
Example 1 - basic check:
function getFoo(foo: string): void {
//
}
function getBar(bar: string| undefined) {
getFoo(bar); //ERROR: "bar" can be undefined
if (isDefined(bar)) {
getFoo(bar); // Ok now, typescript knows that "bar' is defined
}
}
Example 2 - types respect:
function getFoo(foo: string): void {
//
}
function getBar(bar: number | undefined) {
getFoo(bar); // ERROR: "number | undefined" is not assignable to "string"
if (isDefined(bar)) {
getFoo(bar); // ERROR: "number" is not assignable to "string", but it's ok - we know it's number
}
}
UPDATE (Sept 4, 2020)
You can now use the ??
operator to validate null
and undefined
"values" and set a default value. For example:
const foo = null;
const bar = foo ?? 'exampleValue';
console.log(bar); // This will print 'exampleValue' due to the value condition of the foo constant, in this case, a null value
As a verbose way, if you want to compare null and undefined values ONLY, use the following example code for reference:
const incomingValue : string = undefined;
const somethingToCompare : string = incomingValue; // If the line above is not declared, TypeScript will return an excepion
if (somethingToCompare == (undefined || null)) {
console.log(`Incoming value is: ${somethingToCompare}`);
}
If incomingValue
is not declared, TypeScript should return an exception. If this is declared but not defined, the console.log()
will return "Incoming value is: undefined". Note we are not using the strict equals operator.
The "correct" way (check the other answers for details), if the incomingValue
is not a boolean
type, just evaluate if its value is true, this will be evaluated according to the constant/variable type. A true
string have to be defined explicitly as string using the = ''
assignation. If not, it will be evaluated as false
. Let's check this case using the same context:
const incomingValue : string = undefined;
const somethingToCompare0 : string = 'Trumpet';
const somethingToCompare1 : string = incomingValue;
if (somethingToCompare0) {
console.log(`somethingToCompare0 is: ${somethingToCompare0}`); // Will return "somethingToCompare0 is: Trumpet"
}
// Now, we will evaluate the second constant
if (somethingToCompare1) {
console.log(`somethingToCompare1 is: ${somethingToCompare1}`); // Launched if incomingValue is defined
} else {
console.log(`somethingToCompare1 is: ${somethingToCompare1}`); // Launched if incomingValue is undefined. Will return "somethingToCompare1 is: undefined"
}
If you are using TypeScript, it is a better approach to let the compiler check for nulls and undefineds (or the possibility thereof), rather than checking for them at run-time. (If you do want to check at run-time, then as many answers indicate, just use value == null
).
Use the compile option strictNullChecks
to tell the compiler to choke on possible null or undefined values. If you set this option, and then there is a situation where you do want to allow null and undefined, you can define the type as Type | null | undefined
.
If you want to pass tslint
without setting strict-boolean-expressions
to allow-null-union
or allow-undefined-union
, you need to use isNullOrUndefined
from node
's util
module or roll your own:
// tslint:disable:no-null-keyword
export const isNullOrUndefined =
<T>(obj: T | null | undefined): obj is null | undefined => {
return typeof obj === "undefined" || obj === null;
};
// tslint:enable:no-null-keyword
Not exactly syntactic sugar but useful when your tslint rules are strict.
May be to late! but you can use ??
operator in typescript.
see https://mariusschulz.com/blog/nullish-coalescing-the-operator-in-typescript
All,
The answer with the most votes, does not really work if you are working with an object. In that case, if a property is not present, the check will not work. And that was the issue in our case: see this sample:
var x =
{ name: "Homer", LastName: "Simpson" };
var y =
{ name: "Marge"} ;
var z =
{ name: "Bart" , LastName: undefined} ;
var a =
{ name: "Lisa" , LastName: ""} ;
var hasLastNameX = x.LastName != null;
var hasLastNameY = y.LastName != null;
var hasLastNameZ = z.LastName != null;
var hasLastNameA = a.LastName != null;
alert (hasLastNameX + ' ' + hasLastNameY + ' ' + hasLastNameZ + ' ' + hasLastNameA);
var hasLastNameXX = x.LastName !== null;
var hasLastNameYY = y.LastName !== null;
var hasLastNameZZ = z.LastName !== null;
var hasLastNameAA = a.LastName !== null;
alert (hasLastNameXX + ' ' + hasLastNameYY + ' ' + hasLastNameZZ + ' ' + hasLastNameAA);
Outcome:
true , false, false , true (in case of !=)
true , true, true, true (in case of !==) => so in this sample not the correct answer
plunkr link: https://plnkr.co/edit/BJpVHD95FhKlpHp1skUE
I had this issue and some of the answer work just fine for JS
but not for TS
here is the reason.
//JS
let couldBeNullOrUndefined;
if(couldBeNullOrUndefined == null) {
console.log('null OR undefined', couldBeNullOrUndefined);
} else {
console.log('Has some value', couldBeNullOrUndefined);
}
That is all good as JS has no Types
//TS
let couldBeNullOrUndefined?: string | null; // THIS NEEDS TO BE TYPED AS undefined || null || Type(string)
if(couldBeNullOrUndefined === null) { // TS should always use strict-check
console.log('null OR undefined', couldBeNullOrUndefined);
} else {
console.log('Has some value', couldBeNullOrUndefined);
}
In TS if the variable wasn't defined with null
when you try to check for that null
the tslint
| compiler will complain.
//tslint.json
...
"triple-equals":[true],
...
let couldBeNullOrUndefined?: string; // to fix it add | null
Types of property 'couldBeNullOrUndefined' are incompatible.
Type 'string | null' is not assignable to type 'string | undefined'.
Type 'null' is not assignable to type 'string | undefined'.
careful if you're using local storage, you can end up with the string undefined rather than the value undefined:
localStorage.setItem('mykey',JSON.stringify(undefined));
localStorage.getItem('mykey') === "undefined"
true
People may find this useful: https://github.com/angular/components/blob/master/src/cdk/coercion/boolean-property.spec.ts
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/** Coerces a data-bound value (typically a string) to a boolean. */
export function coerceBooleanProperty(value: any): boolean {
return value != null && `${value}` !== 'false';
}
import {coerceBooleanProperty} from './boolean-property';
describe('coerceBooleanProperty', () => {
it('should coerce undefined to false', () => {
expect(coerceBooleanProperty(undefined)).toBe(false);
});
it('should coerce null to false', () => {
expect(coerceBooleanProperty(null)).toBe(false);
});
it('should coerce the empty string to true', () => {
expect(coerceBooleanProperty('')).toBe(true);
});
it('should coerce zero to true', () => {
expect(coerceBooleanProperty(0)).toBe(true);
});
it('should coerce the string "false" to false', () => {
expect(coerceBooleanProperty('false')).toBe(false);
});
it('should coerce the boolean false to false', () => {
expect(coerceBooleanProperty(false)).toBe(false);
});
it('should coerce the boolean true to true', () => {
expect(coerceBooleanProperty(true)).toBe(true);
});
it('should coerce the string "true" to true', () => {
expect(coerceBooleanProperty('true')).toBe(true);
});
it('should coerce an arbitrary string to true', () => {
expect(coerceBooleanProperty('pink')).toBe(true);
});
it('should coerce an object to true', () => {
expect(coerceBooleanProperty({})).toBe(true);
});
it('should coerce an array to true', () => {
expect(coerceBooleanProperty([])).toBe(true);
});
});
Since TypeScript is a typed superset of ES6 JavaScript. And lodash are a library of javascript.
Using lodash to checks if value is null or undefined can be done using _.isNil()
.
_.isNil(value)
value (*): The value to check.
(boolean): Returns true if value is nullish, else false.
_.isNil(null);
// => true
_.isNil(void 0);
// => true
_.isNil(NaN);
// => false
We use a helper hasValue
that both checks for nulls/undefined and ensures via TypeScript that unnecessary checks are not performed. (The latter is similar to how TS would complain about if ("a" === undefined)
, since it is always false).
Using this consistently is always safe, unlike !val
which matches empty strings, zero, etc. It also avoid the use of fuzzy ==
matching which is almost always a bad practice - no need to introduce an exception.
type NullPart<T> = T & (null | undefined);
// Ensures unnecessary checks aren't performed - only a valid call if
// value could be nullable *and* could be non-nullable
type MustBeAmbiguouslyNullable<T> = NullPart<T> extends never
? never
: NonNullable<T> extends never
? never
: T;
export function hasValue<T>(
value: MustBeAmbiguouslyNullable<T>,
): value is NonNullable<MustBeAmbiguouslyNullable<T>> {
return (value as unknown) !== undefined && (value as unknown) !== null;
}
export function hasValueFn<T, A>(
value: MustBeAmbiguouslyNullable<T>,
thenFn: (value: NonNullable<T>) => A,
): A | undefined {
// Undefined matches .? syntax result
return hasValue(value) ? thenFn(value) : undefined;
}
Since TypeScript is strongly-typed
I couldn't find this in it's docs and I have doubts about it... – pawciobielif () {}
since that will also be true for0
. – Tom el Safadi