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
Answer from Fenton on Stack Overflow"a == null"
"a is undefined"
"b == null"
"b === null"
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"
if( value ) {
}
will evaluate to true if value is not:
nullundefinedNaN- empty string
'' 0false
typescript includes javascript rules.
[AskJS] Nullish Check in conditional
How to use Nullish Coalescing in Typescript
Nullish Coalescing Operator vs Logical OR
typescript - Nullish Coalescing is not working in this case - Stack Overflow
Videos
I feel like an idiot as this feels like it should be an obvious answer, but every time this has come up I've failed to think of a satisfactory answer, and google with such basic terms is useless.
If I have a value that I want to put in a full conditional (an if() ) to check if it is nullish (null or undefined) but not falsy, what's a clean, concise, and clear syntax?
We have the nullish coallescing operator, but that acts like the ternary/conditional operator and not like a comparison operator. If I have a block of statements I want to run IF the value is nullish (or if it is NOT nullish) but not falsy, I don't feel like I have any option other than to say the explicit if ( value === undefined || value === null ) {...}
I can write my own isNullish() or use constructs like if( !(value ?? true) ) { ...} but these are awful, and I feel like I must be missing something obvious.
This obviously isn't a big deal, checking the two values isn't terrible, but is there something I'm missing that lets me say if( ??nullish ) { ... } when I have more than simple defaulting to do?
[Edit: The answer I was seeking is value == null or value == undefined, as these specific checkes are an exception to the normal practice of avoiding loose comparison, if nullish is what I want to check for. Thanks for the help, I was indeed missing something basic]
It's a precedence issue. Your code is being evaluated as:
if (data?.["myKeys"]?.indexOf("index1") ?? (-1 === -1)) {
// ββββββββββββββββββββββββββββββββββββββββ^βββββββββ^
console.log("Why is it true");
}
but your intention is:
if ((data?.["myKeys"]?.indexOf("index1") ?? -1) === -1) {
// β^βββββββββββββββββββββββββββββββββββββββββ^
console.log("Why is it true");
}
Oddly, I don't see precedence discussed in the proposal though it is mentioned in the draft spec as Jonas mentions, and it does come up in the issues.
As you can see, this is consistent with the precedence of ||, which is its very, very near relative:
const a = 2;
const b = -1;
console.log(`${a} || ${b} === ${b}: ${a || b === b}`);
console.log(`(${a} || ${b}) === ${b}: ${(a || b) === b}`);
console.log(`${a} || (${b} === ${b}): ${a || (b === b)}`);
According to the draft spec, ?? has lower precedence than || (presumably just lower). (To avoid confusion, it's also not allowed in an && or || expression.)
To quote from the draft:
?? has lower precedence than ||
Or in other words, your code behaves roughly like:
data?.["myKeys"]?.indexOf("index0") || -1 === -1
And that'll be treated as:
(data?.["myKeys"]?.indexOf("index0")) || (-1 === -1)
Take this interface for example
interface Item {
value?: number
}Which among the two do you prefer if you will be accessing the value property of an item and why?
console.log(item.value ?? 1.00) // 1.00 is the fallback value
console.log(item.value || 1.00) // 1.00 is the fallback value
Personally, I prefer to use the nullish coalescing operator ?? for fallback values since it's more explicit and it sames me from the weird falsy values that JavaScript has.
The nullish coalescing operator DOES NOT apply to this case:
The nullish coalescing (??) operator is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.
See the docs
In this case you have a simple union of type Day | 0, you just have to check manually:
for (let i = 0; i < 4; i++) {
const item = daysArray[i];
if (typeof item === "number") {
console.log(0);
} else {
console.log(item.dayNumber);
}
}
The nullish coalescing does not apply in this case, here is documentation of nullish coalescing with examples of how it's supposed to be used: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing
The reason why your code is giving red squiggly is because the element at daysArray[i] might be either a number or an object which has the shape of the Day interface. so trying to access daysArray[i].dayNumber is not entirely correct, first you have to check that it's an object and not a number. this way typescript compiler will infer the type of daysArray[i] to be of type Day and will allow you to access dayNumber property.
Here is a working example:
type Day = {
dayNumber: number;
color: string;
isBooked: boolean;
};
const myDay: Day = {
dayNumber: 12,
color: "blue",
isBooked: false
};
const daysArray: (Day | 0)[] = [0, 0, 0, myDay];
for (let i = 0; i < daysArray.length; i++) {
const element = daysArray[i];
if(typeof element === 'object') {
console.log(element.dayNumber);
}
}
Please refer to the official documentation for type narrowing: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#typeof-type-guards