152

TypeScript 3.7 now supports the optional chaining operator. Hence, you can write code such as:

const value = a?.b?.c;

I.e., you can use this operator to access properties of an object, where the object itself may be null or undefined. Now what I would like to do is basically the same, but the property names are dynamic:

const value = a?[b]?.c;

However, there I get a syntax error:

error TS1005: ':' expected.

What am I doing wrong here? Is this even possible?

The proposal seems to imply that this is not possible (but maybe I get the syntax examples wrong).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Golo Roden
  • 140,679
  • 96
  • 298
  • 425

2 Answers2

276

When accessing a property using bracket notation and optional chaining, you need to use a dot in addition to the brackets:

const value = a?.[b]?.c;

This is the syntax that was adopted by the TC39 proposal, because otherwise it's hard for the parser to figure out if this ? is part of a ternary expression or part of optional chaining.

The way I think about it: the symbol for optional chaining isn't ?, it's ?.. If you're doing optional chaining, you'll always be using both characters.

Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • 18
    I’d replace _hard_ with _impossible_. – vol7ron Nov 09 '19 at 16:17
  • 1
    @vol7ron why so - i think it can look forward for `:` – AnArrayOfFunctions Nov 09 '19 at 20:40
  • 1
    It wouldn’t be able to distinguish, especially when there are errors. – vol7ron Nov 09 '19 at 20:49
  • @AnArrayOfFunctions Won't happen. There are already a few places in the language where this forward-looking would solve problems. Just think how the statement `function(){};` or `{a: 1}.a;` are both a syntax error. Also: Nested ternaries are already hard to parse (what does `a?[...b][1]?c:d?.e:f` mean). Better not make it more difficult by overloading `?`. – Robert Jul 21 '20 at 05:10
  • 2
    Wow, that is super-unintuitive since the optional chaining syntax minus the "optional" part is invalid. You can't run chaining as `a.[b].c`, so `a?.[b]?.c` is only going to be discovered by those who run into the issue and search online. Maybe a proposal could be made to enable `a.[b].c` chaining syntax? – bsplosion Jun 04 '21 at 13:49
21

The Optional Chaining operator is ?.

Here are some examples for nullable property and function handling.

const example = {a: ["first", {b:3}, false]}

// Properties
example?.a  // ["first", {b:3}, false]
example?.b  // undefined

// Dynamic properties ?.[]
example?.a?.[0]     // "first"
example?.a?.[1]?.a  // undefined
example?.a?.[1]?.b  // 3

// Functions ?.()
null?.()                // undefined
validFunction?.()       // result
(() => {return 1})?.()  // 1

Bonus: Default values

?? (Nullish Coalescing) can be used to set a default value if undefined or null.

const notNull = possiblyNull ?? defaultValue
const alsoNotNull = a?.b?.c ?? possiblyNullFallback ?? defaultValue
Gibolt
  • 42,564
  • 15
  • 187
  • 127
  • Is there a difference in doing `a?.b?.c ?? default` vs `a?.b?.c || default`? – nick Nov 29 '21 at 10:21
  • 4
    `||` checks for all falsey values, so `''`, `0` and `false` will go to the default, whereas `??` will only default for `null` and `undefined` – Gibolt Dec 01 '21 at 01:34
  • That's the Nullish coalescing operator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator – massic80 Jun 28 '22 at 22:49