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

Inconsistent/broken narrowing of void #32809

Closed
ethanresnick opened this issue Aug 12, 2019 · 3 comments · Fixed by #33199
Closed

Inconsistent/broken narrowing of void #32809

ethanresnick opened this issue Aug 12, 2019 · 3 comments · Fixed by #33199
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging
Milestone

Comments

@ethanresnick
Copy link
Contributor

ethanresnick commented Aug 12, 2019

TypeScript Version: 3.5.1

Search Terms: void typeof undefined narrow use before assign

Code

// with strictNullChecks
const x2: void = undefined;
const x3: void = undefined;

if(typeof x2 === "undefined") {
    x2 // Error: Variable 'x2' is used before being assigned.
}

if(typeof x3 !== "undefined") {
    x3 // never. x3 should probably be void
}
// without strictNullChecks
const x2: void = undefined;

if(typeof x2 === "undefined") {
    x2 // x2 remains void here, not undefined.
}

if(typeof x2 !== "undefined" && x2 !== null) {
    x2 // x2 remains void here, rather than never.
}

Expected behavior:

Using x2 inside the first conditional in the strictNullChecks example should not error, as the variable absolutely was assigned to before use (whatever its type should be).

Also, the semantics around narrowing void should be consistent when strictNullChecks is on and when it's off. And, based on some of the comments I've seen about void's purpose, it seems like the semantics with strictNullChecks off are the right ones.

Actual behavior:

The use of x2 triggers an error, as mentioned.

And narrowing void is a no-op when strictNullChecks is disabled (i.e., it always results in void), whereas narrowing void can produce never when strictNullChecks is enabled.

Playground Link:
With strictNullChecks: https://www.typescriptlang.org/play/index.html#code/PTAEHcEsBcAtQM7QE6QMbQHIFcA2uBhWAUzQGsEAoNAewDslQAPAJgC5QA3GyAE1AC8obHV7EAZpDrFeAbmr1GTAMwdufQcNESpM+ZUjiAFNACeAB2I1xzFoIFCARCLGTpvRwEpQAb0qgA21AQUABRZGQaZA4ANQBDVDiAI1xiUAByVnTQSARhBBlQJIkotOKpAHNQOIQESAr3ADpKAF9KA2MzS2tmZVAAQgdQZ203GS9ff0CVYLBpTmJkVqA

Without strictNullChecks: https://www.typescriptlang.org/play/index.html?strictNullChecks=false#code/PTAEHcEsBcAsHsCu1QGdoCdIGNoDlEAbQgYVgFNsBrVAKG3gDt1QAPAJgC5QA3eSACagAvKESMB5AGaRG5AQG5akKQApoATwAO5eFLbsRw0QCJxkmXIEmAlKADetUM4OgQrjOQC2AQ1mpefiEKTwAaUEZ4FHNpWXkAOloAX1plNU0dPVcAQmNQMwlYqxNQADJSnLzGIkI7RxdXdw5QT19-QMFQEPJwjB84cgxQOB9GCPIeQcSkoA

@ethanresnick ethanresnick changed the title Narrowing void to undefined produces "used before assigned" error Inconsistent/broken narrowing of void Aug 12, 2019
@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Aug 12, 2019
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Aug 12, 2019
@RyanCavanaugh
Copy link
Member

The only behavior I would consider a bug here is the wrong error message in the first if block. It is nonsense to declare, and more nonsense to inspect, a value of type void, so any weirdness around narrowing is sort of neither here nor there as long as an illegal operation isn't allowed.

@RyanCavanaugh RyanCavanaugh added the Domain: Error Messages The issue relates to error messaging label Aug 12, 2019
@ethanresnick
Copy link
Contributor Author

ethanresnick commented Aug 12, 2019

It is nonsense to declare, and more nonsense to inspect, a value of type void

Isn't that precisely why narrowing should be a no-op? To be able to narrow out undefined and get to never (the if (typeof x3 !== "undefined") case) seems to be the type system leaking one definition of void (its similarity to undefined) into another part of the system, where it will be both invalid at runtime (since the void value could be anything) and seems to violate the semantics of void that say "this thing should always be opaque" (and hence uninspectable).

I guess narrowing to never isn't harmful, at least, but it begs the question of what type x2 should have in the first if block if narrowing's gonna be allowed (and the fact that this would be effected by strictNullChecks still seems weird).

@RyanCavanaugh
Copy link
Member

I find that convincing. The problem with x3 narrowing to never is that you can then pass it to any function.

Probably the right answer is that in all cases, void shouldn't narrow at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Error Messages The issue relates to error messaging
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants