Nullish Coalescing is not working in this case

979 views Asked by At

In the following code I want to print out the "dayNumber" property, in case the item is an object otherwise It should print out the number 0. I can't get rid of the error and I don't understand why.

code with error

I'm trying to use the nullish coalescing operator, which seams appropriate in this case.

4

There are 4 answers

0
kareem alkoul On

Because typescript is a safety type and uses Type Guards to prevent you from calling a parameter don't declare it, so you can't call dayNumber when the type is Literal 0 the nullish coalescing and Optional Chaining use it when the parameter/property is declare as optional in TypeScript and The onion of type 0 and Day doesn't have this property (but in JS you can do it because don't have types to compile check it and complain), so for solve the problem you must use type guards technics (in, instanceof, ..etc) it makes more code, or declare the array as any[] and escape from type checking

2
Nullndr On

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);
  }
} 
4
Gabriel Pureliani On

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

0
Ashot Hayrapetyan On

You can do it like this

console.log((daysArray[i] as Day).dayNumber ?? 0);