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);
}
}
Answer from Nullndr on Stack OverflowVideos
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
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.