question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Optional chaining not working with void type

See original GitHub issue

Demo

playground demo

TypeScript source with nightly version 3.8.0-dev.20191224

type Address = {
    city: string
}

type User = {
    home: Address | undefined
    work: Address | void
}

declare let u: User

u.home?.city
u.work?.city

JavaScript output the same for both "work" and "home" properties

"use strict";
var _a, _b;
(_a = u.work) === null || _a === void 0 ? void 0 : _a.city;
(_b = u.home) === null || _b === void 0 ? void 0 : _b.city;

Bug

If you run the code above, you will see that for u.home?.city there are no errors. But for u.work?.city there is an error:

Error: Property 'city' does not exist on type 'void | Address'

Expectation

Optional chaining works for both 'undefined' and 'void' types the same way.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:20
  • Comments:22 (9 by maintainers)

github_iconTop GitHub Comments

13reactions
overshomcommented, Dec 26, 2019

I believe my issue not about void itself. We could leave void definition the same as now. It’s about optional chaining doesn't skip empty types in union type.

Not working, but expected to work:

type Address = {
    city: string
}

declare let value: Address | void | null | undefined | never

value?.city

Working good:

declare let value: Address | null | undefined | never

value?.city

Why void breaks optional chaining - not clear for me still. What stops us from adding support for optional chaining with void in union type - not clear.

4reactions
Raiondesucommented, Dec 27, 2019

Actually, this is a big issue for functions with optional contexts.

Currently, the only way to make a function that accepts an optional context is to define it as
this: SomeType | void, since this?: SomeType doesn’t work.

Due to this issue, it’s currently impossible to use optional chaining inside the function to access properties of such context:

type Foo = { bar?: { baz: string; }; };

function example(this: Foo | void, value: string) {
  return this?.bar?.baz ?? value; // Currently an error here
}

example('default string');

One could argue that this is solvable by using undefined instead of void, but this forces all invocations to provide the context of undefined:

type Foo = { bar?: { baz: string; }; };

function example(this: Foo | undefined, value: string) {
  return this?.bar?.baz ?? value; // No error, cool
}

example('default string'); // "The 'this' context of type 'void' is not assignable to method's 'this' of type 'Foo | undefined'." 😕

So, currently, optional chaining is broken completely for functions with optional contexts. See more examples in this playground.


I, personally, have many uses for functions like this in my libraries and projects. And I believe other people have use-cases too.

Read more comments on GitHub >

github_iconTop Results From Across the Web

5 Ways Converting to Optional Chaining Can Break Your Code
The optional chaining operator lets you write concise and safe chains of connected objects when some of those objects can be null or...
Read more >
Optional chaining (?.) - JavaScript - MDN Web Docs - Mozilla
The optional chaining ( ?. ) operator accesses an object's property or calls a function. If the object accessed or function called is ......
Read more >
Property doesn't exist on type 'object' when using optional ...
The optional chaining operator (?.) enables you to read the value of a property located deep within a chain of connected objects without ......
Read more >
Optional Chaining: The ?. Operator in TypeScript
Optional chaining is not a feature specific to TypeScript. The ?. operator got added to the ECMAScript standard as part of ES2020.
Read more >
Documentation - TypeScript 3.7
For context, there have been over 23,000 issues on the TypeScript issue tracker since then. At its core, optional chaining lets us write...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found