Closed
Description
Bug Report
🔎 Search Terms
void, union, user-defined type guard
🕗 Version & Regression Information
v4.2.0-dev.20210207. It stayed this way in 4.3.0-dev.20210211
- This changed between versions 4.1 and 4.2 RC
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
void
⏯ Playground Link
Playground link with relevant code
💻 Code
function isDefined<T>(value: T | undefined | null | void): value is T {
return value !== undefined && value !== null;
}
declare const foo: string | undefined;
if (isDefined(foo)) {
// 4.2: foo is string | undefined
// 4.1: foo is string
console.log(foo.toUpperCase());
}
🙁 Actual behavior
Compile-time error. foo
is string | undefined
🙂 Expected behavior
No compile-time error. foo
is string
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]Unions containing `void` behave differently from 4.2 on[/-][+]Inference to unions containing `void` behave differently from 4.2 on[/+]DanielRosenwasser commentedon Feb 13, 2021
Likely involves the changes from #42353, and I have theories of what we probably do, but @ahejlsberg will surely have a better idea.
ahejlsberg commentedon Feb 15, 2021
Yeah, this one is an effect of us now reducing
void | undefined
to justvoid
. With that reduction, the type of thevalue
parameter becomesT | null | void
, but then thevalue !== undefined
test in the body doesn't removevoid
because we sometimes think ofvoid
possibly being any type. So, we're trying to have our cake and eat it too, and it isn't working.We've had many discussions about our strange
void
semantics, but we have yet to come up with something better that doesn't break the world. However, in the spirit of at least not breaking things, we could dial back and only do thevoid | undefined
tovoid
reduction in cases where we perform subtype reduction. That was our previous behavior.DanielRosenwasser commentedon Feb 17, 2021
@ahejlsberg is that an option? Is it just a matter of special-casing how we invoke literal type reduction? That might be worth it.
ahejlsberg commentedon Feb 17, 2021
Yes, it's an option and it isn't particularly hard to implement. We'd just make the
void | undefined
tovoid
reduction in the literal type reduction pass conditional on whether we are also (in a subsequent pass) performing subtype reduction.