Reputation: 17624
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?
Upvotes: 767
Views: 1306523
Reputation: 981
There are several ways to do it. The most important is to be consistent across your code base. And consider all the pros and cons per case.
With !!
, example:
if (!!value) {
doSomething();
}
Using !!
is the shortest (in terms of amount of symbols). But it has several serious flaws:
With != null
, example:
if (value != null) {
doSomething();
}
Using != null
is the best option which would check for null
and undefined
in one hit. It's more readable than !!
but still has "not intuitive enough" flaw for cross functional teams. I would lean to this option, because it has the least amount of drawbacks.
Using lodash / other library's / self-written isDedined
method, example:
if (isDefined(value)) {
doSomething();
}
It's the most readable approach, and if done properly it won't increase your bundle size that much. But it also has it's flaws. Using it for single checks will certainly work. But what if you need to do it in cycle? It would be much slower than using a juggling-check.
Upvotes: 0
Reputation: 7139
It can be done like this:
// value is the value which you want to check
[undefined, null].includes(value)
Upvotes: 5
Reputation: 9415
Although Typescript is a strongly typed language, it has the same problems with pointers and variables initialization inherited from Javascript.
Javascript doesn't check whether a variable exists in the context, the so common undefined
status.
to evaluate if value ISN'T null
,undefined
,0
,false
,""
, or NaN
:
if ( value )
or
if ( !!value )
for negative conditional, check if the value is null
,undefined
,0
,false
,""
,or NaN
:
if ( !value )
to test if is null
or undefined
:
if ( value == null )
to test only null
:
if ( value === null )
to test only undefined
:
if ( value === undefined )
1- It will evaluate to true if value is not: null
, undefined
, NaN
, empty string ''
, 0
, false
If the value is null
,undefined
,NaN
,empty string
,0
, or false
, will go to the else condition.
if ( value ) {
console.log('value is something different from 0, "", false, NaN, null, undefined');
} else {
console.log('value is 0, "", false, NaN, null or undefined');
}
if ( !!value ) {
console.log('value is something different from 0, "", false, NaN, null, undefined');
} else {
console.log('value is 0, "", false, NaN, null or undefined');
}
2- If you want a negative condition, then you'll need to use:
if ( !value ) {
console.log('value is 0, "", false, NaN, null or undefined');
} else {
console.log('value is something different from 0, "", false, NaN, null, undefined');
}
3- It will evaluate if value is null
or undefined
if ( value == null ) {
console.log('is null or undefined');
} else {
console.log('it isnt null neither undefined');
}
4- Using a test with boolean values doesn't work.
It will NOT evaluate to true neither to false if value is null
, undefined
, 0
, empty string
, NaN
Both conditions will always go to the else condition.
With the exception if value is a boolean variable.
if ( value==true ) {
} else {
}
if ( value==false ) {
} else {
}
Upvotes: 47
Reputation: 19
You could use:
if (!!variable) {}
it equals writting
it (variable != null && variable != undefined) {}
Upvotes: -3
Reputation: 1472
You can do this easily with a ternary operator and the new nullish coalesce operator.
First: check to see if it is true using the ternary. If so return false so the if statement does not run.
Second: because you now know the value is falsey, you can use the nullish coalesce operator to return true if it is nullish. Since it will return itself for any other value, if it is not nullish it will fail the if statement correctly.
let x = true;
console.log("starting tests")
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x = false
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x = 0;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x=1;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x="";
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x="hello world";
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x=null;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
x=undefined;
if (x?false:x ?? true){
console.log(x,"is nullish")
}
Upvotes: 1
Reputation: 103
May be to late! but you can use ??
operator in typescript.
see https://mariusschulz.com/blog/nullish-coalescing-the-operator-in-typescript
Upvotes: 2
Reputation: 7355
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;
}
Upvotes: 2
Reputation: 21387
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();
Upvotes: 192
Reputation: 312
The simplest way is to use:
import { isNullOrUndefined } from 'util';
and than:
if (!isNullOrUndefined(foo))
Upvotes: 3
Reputation: 457
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"
}
Upvotes: 10
Reputation: 276235
Does TypeScript has dedicated function or syntax sugar for this
TypeScript fully understands the JavaScript version which is something == null
.
TypeScript will correctly rule out both null
and undefined
with such checks.
https://basarat.gitbook.io/typescript/recap/null-undefined
Upvotes: 93
Reputation: 17581
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
}
}
Upvotes: 39
Reputation: 17213
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);
});
});
Upvotes: 0
Reputation: 695
I always write it like this:
var foo:string;
if(!foo){
foo="something";
}
This will work fine and I think it's very readable.
Upvotes: -8
Reputation: 3010
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.
Upvotes: 31
Reputation: 273
Usually I do the juggling-check as Fenton already discussed. To make it more readable, you can use isNil from ramda.
import * as isNil from 'ramda/src/isNil';
totalAmount = isNil(totalAmount ) ? 0 : totalAmount ;
Upvotes: 0
Reputation: 1335
Late to join this thread but I find this JavaScript hack very handy in checking whether a value is undefined
if(typeof(something) === 'undefined'){
// Yes this is undefined
}
Upvotes: 0
Reputation: 14022
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'.
Upvotes: 0
Reputation:
A faster and shorter notation for null
checks can be:
value == null ? "UNDEFINED" : value
This line is equivalent to:
if(value == null) {
console.log("UNDEFINED")
} else {
console.log(value)
}
Especially when you have a lot of null
check it is a nice short notation.
Upvotes: -1
Reputation: 47
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
Upvotes: 1
Reputation: 251192
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"
Upvotes: 695
Reputation: 5173
if( value ) {
}
will evaluate to true
if value
is not:
null
undefined
NaN
''
0
false
typescript includes javascript rules.
Upvotes: 480
Reputation: 6810
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.
Upvotes: 43
Reputation: 1815
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.
Upvotes: 8
Reputation: 2663
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
Upvotes: 0
Reputation:
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
.
Upvotes: 7
Reputation: 6597
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:
Upvotes: 46