Skip to main content

useOptionalChain (since v0.10.0)

Enforce using concise optional chain instead of chained logical expressions.

TypeScript 3.7 added support for the optional chain operator. This operator allows you to safely access properties and methods on objects when they are potentially null or undefined. The optional chain operator only chains when the property value is null or undefined. It is much safer than relying upon logical operator chaining; which chains on any truthy value.

Examples

Invalid

foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz
nursery/useOptionalChain.js:1:1 lint/nursery/useOptionalChain  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   Change to an optional chain.
  
     nursery/useOptionalChain.js:1:1
    
  1  foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
   Suggested fix: Change to an optional chain.
  
      | @@ -1 +1 @@
  0   | - foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz
    0 | + foo?.bar?.baz?.buzz
  
foo.bar && foo.bar.baz.buzz
nursery/useOptionalChain.js:1:1 lint/nursery/useOptionalChain  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   Change to an optional chain.
  
     nursery/useOptionalChain.js:1:1
    
  1  foo.bar && foo.bar.baz.buzz
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
   Suggested fix: Change to an optional chain.
  
      | @@ -1 +1 @@
  0   | - foo.bar && foo.bar.baz.buzz
    0 | + foo.bar?.baz.buzz
  
foo !== undefined && foo.bar != undefined && foo.bar.baz !== null && foo.bar.baz.buzz
nursery/useOptionalChain.js:1:1 lint/nursery/useOptionalChain  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   Change to an optional chain.
  
     nursery/useOptionalChain.js:1:1
    
  1  foo !== undefined && foo.bar != undefined && foo.bar.baz !== null && foo.bar.baz.buzz
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
   Suggested fix: Change to an optional chain.
  
      | @@ -1 +1 @@
  0   | - foo !== undefined && foo.bar != undefined && foo.bar.baz !== null && foo.bar.baz.buzz
    0 | + foo?.bar?.baz?.buzz
  
((foo || {}).bar || {}).baz;
nursery/useOptionalChain.js:1:1 lint/nursery/useOptionalChain  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   Change to an optional chain.
  
     nursery/useOptionalChain.js:1:1
    
  1  ((foo || {}).bar || {}).baz;
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
   Suggested fix: Change to an optional chain.
  
      | @@ -1 +1 @@
  0   | - ((foo || {}).bar || {}).baz;
    0 | + foo?.bar?.baz;
  
(await (foo1 || {}).foo2 || {}).foo3;
nursery/useOptionalChain.js:1:1 lint/nursery/useOptionalChain  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   Change to an optional chain.
  
     nursery/useOptionalChain.js:1:1
    
  1  (await (foo1 || {}).foo2 || {}).foo3;
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
   Suggested fix: Change to an optional chain.
  
      | @@ -1 +1 @@
  0   | - (await (foo1 || {}).foo2 || {}).foo3;
    0 | + (await foo1?.foo2)?.foo3;
  
(((typeof x) as string) || {}).bar;
nursery/useOptionalChain.js:1:1 lint/nursery/useOptionalChain  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

   Change to an optional chain.
  
     nursery/useOptionalChain.js:1:1
    
  1  (((typeof x) as string) || {}).bar;
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
   Suggested fix: Change to an optional chain.
  
      | @@ -1 +1 @@
  0   | - (((typeof x) as string) || {}).bar;
    0 | + ((typeof x) as string)?.bar;
  

Valid

foo && bar;
foo || {};
(foo = 2 || {}).bar;
foo || foo.bar;
foo["some long"] && foo["some long string"].baz