1

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.

3 Answers3

2

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);
  }
} 
Nullndr
  • 1,624
  • 1
  • 6
  • 24
1

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

  • Great explanation, thank you very much!! Something is still not clear though. From MDN: __"The nullish coalescing operator treats undefined and null as specific values. So does the optional chaining operator (?.), which is useful to access a property of an object which may be null or undefined. Combining them, you can safely access a property of an object which may be nullish and provide a default value if it is."__ So, this " daysArray[i]?.dayNumber ?? 0 " should work...but it doesn't. – Cristian Cassetta Mar 21 '23 at 10:14
  • @CristianCassetta the `?.` operator applies to unions of type `T | null | undefined`. Again, this is not your case since `daysArray[i]` is of type `Day | 0` – Nullndr Mar 21 '23 at 11:12
  • if a variable (in your case `daysArray[i]` ) were of type: `object | null`, or the type were `object | undefined`, or the type were `object | null | undefined`, in these cases you would use optional chaining, but the variable type in your case is: `object | 0` and here lies the problem, you cannot chain into a number. – Gabriel Pureliani Mar 21 '23 at 11:15
  • Ok, I'm getting the hang of it. Thanks everybody, really great community. – Cristian Cassetta Mar 21 '23 at 12:08
0

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

kareem alkoul
  • 739
  • 6
  • 13