Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

void | T allows narrowing of undefined | T #57855

Closed
robbiespeed opened this issue Mar 19, 2024 · 7 comments
Closed

void | T allows narrowing of undefined | T #57855

robbiespeed opened this issue Mar 19, 2024 · 7 comments
Labels
Duplicate An existing issue was already created

Comments

@robbiespeed
Copy link

robbiespeed commented Mar 19, 2024

πŸ”Ž Search Terms

void, union, undefined, narrowing

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about void

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.2#code/GYVwdgxgLglg9mABMOdEAoBuAuRm4wAmiAPomCALYBGApgE4CUuFNDpi4htwMYtxAN4AoRIgD04vAWJ0AFgENMfAOaIANjADWtTmG69+hUYhjAMUAJ4AHWnHOZEAXheIARHGoArWtDeNEETExTABuCSl+TAYTMXpaKBB6MFCTAF8TMwxHAEJXLh4+AQCg4PjE5LxwyXIqOnoMahAoRAg4EHVieIV1dUtEOkQFMEsoOVVGdOETcqSU4QzhUEhYBAGFBvRmRABnKHpVQMRZyrc5Wl64N0Q01OE2sD31gC9cLecAPmkiZ3X6O5QcHQ1A2W0Y1UicBaPXUcAA7gIlqhgQpnmCIUNLgjZM1ELR9DtONZjgk5ocFLt9odhEA

πŸ’» Code

function foo (v: void | number): number | undefined {
  // void behaving like undefined
  if (typeof v === "object") {
    v; // never
    return;
  }
  if (v !== undefined) {
    return v; // number (but could really be anything)
  }

  return;
}

function bar (): string { return "hello" };

const baz: () => void = bar;

foo(bar()); // not allowed
foo(baz()); // allowed but ends up returning a string 

πŸ™ Actual behavior

void | number narrows as if it were undefined | number leading to incorrect application state.

πŸ™‚ Expected behavior

void | number should only narrow to number using v === numericLiteral or typeof v === "number"

Additional information about the issue

It's a bit unclear whether typeof v === "object" should narrow v to object | null instead of never, since in some cases like function return types void acts as unknown.

As an aside it seems like void isn't very useful now that we have unknown (modified playground replacing void with unknown and it catches the issue).

@MartinJohns
Copy link
Contributor

Related: #42709

In general a union with void makes absolutely no sense. Unfortunately a lot of people think void means "no value", but that's not the case.

@robbiespeed
Copy link
Author

@MartinJohns Thanks for pointing me to that issue I was tempted to make a feature request for at the very least inferring function returns as undefined by default, if not outright removing void in strict mode.

I do agree that in general void shouldn't be used with a union, but it illustrates the inconsistent behaviour of void well. An example without a union is:

declare const v: void;
if (v !== undefined) {
  v; // type is never (void narrowed as if it was undefined)
} else {
  v; // void?
}

@RyanCavanaugh
Copy link
Member

I think #42709 is the controlling issue here - removing all conflations of void and undefined is really the knot to untangle

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Mar 19, 2024
@robbiespeed
Copy link
Author

@RyanCavanaugh I don't agree, that issue seems to be centered around replacing void with undefined as the default inferred value for non returning functions, but still allowing explicit use of void.

This specific bug will still be present regardless of the decision there.

@RyanCavanaugh
Copy link
Member

There's #46837 then

@robbiespeed
Copy link
Author

Just saw that as well, will close this.

@fatcerberus
Copy link

fatcerberus commented Mar 20, 2024

I still get a kick out of this comment

We've spent several dozen person-hours in the past few months beating this particular horse to death without much forward progress, but I remain optimistic that we'll eventually make some progress on it.

Given that that was posted over 3 years ago, I think it's safe to say the horse is well and truly dead by now and any further progress on that front will almost assuredly require enlisting the services of a necromancer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants