Repository navigation
Inconsistent/broken narrowing of void #32809
Description
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
Activity
[-]Narrowing void to undefined produces "used before assigned" error[/-][+]Inconsistent/broken narrowing of void[/+]RyanCavanaugh commentedon Aug 12, 2019
The only behavior I would consider a bug here is the wrong error message in the first
ifblock. It is nonsense to declare, and more nonsense to inspect, a value of typevoid, so any weirdness around narrowing is sort of neither here nor there as long as an illegal operation isn't allowed.ethanresnick commentedon Aug 12, 2019
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 ofvoid(its similarity toundefined) into another part of the system, where it will be both invalid at runtime (since thevoidvalue 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
neverisn't harmful, at least, but it begs the question of what typex2should have in the firstifblock if narrowing's gonna be allowed (and the fact that this would be effected by strictNullChecks still seems weird).RyanCavanaugh commentedon Aug 12, 2019
I find that convincing. The problem with
x3narrowing toneveris that you can then pass it to any function.Probably the right answer is that in all cases,
voidshouldn't narrow at all.Merge pull request #33199 from jack-williams/fix-32809