TypeScript: Intersection with void should resolve to never
🔎 Search Terms
intersection, void
🕗 Version & Regression Information
- This is a crash
- This changed between versions ______ and _______
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
void - I was unable to test this on prior versions because _______
⏯ Playground Link
https://www.typescriptlang.org/play?#code/C4TwDgpgBAmlC8UDeUCGAuKBnYAnAlgHYDmUAvlAGRQBuA9vgCYBQQA
💻 Code
type Y = { a: string } & void
void is a more restricted type of undefined specifically to describe function that “returns nothing”.
In the JavaScript land, it actually returns an implicit undefined.
So for all due and purposes, I believe void should have similar behavior as undefined whenever possible.
For undefined, intersection type resolves to never
type Y = { a: string } & undefined // never
🙁 Actual behavior
// Your code here
type Y = { a: string } & void // { a: string } & void
🙂 Expected behavior
// Your code here
type Y = { a: string } & void // never
Additional information about the issue
No response
About this issue
- Original URL
- State: closed
- Created 10 months ago
- Comments: 16 (12 by maintainers)
The way I think of it is that
voidis likeunknownwith some special assignability restrictions when interacting with it directly, but those disappear and it acts more likeunknownwhen it’s being compared across two return types in signatures.void & { x: string }has those same cannot-use-directly restrictions, but it behaves as expected when part of a signature:[playground]
Is it useful? Not that I can tell. Is it weird? Yes. But is it about as internally consistent as it can be given the weird rules? I think so.
I don’t know if this has been linked yet but if not: #42709
voidis just weird in general, but any changes around it would likely be in the direction of tackling #42709, based on past comments from maintainers.In particular, this remark from there is in line with what you’re saying:
If
const f: () => void = () => ({ x: "hello ")is legal, then I think quite clearlyvoid & { x: string }is notnever.Every time I think about
voidin TypeScript too much I start feeling this empty despair, like logic has been swallowed up by some great… uh, what’s the word? It’s like “hole” but that’s not it. Gulf? Abyss? Chasm? Ah, never mind. Anyway,voidis inconsistent in TypeScript but I don’t know that messing with it would be an improvement.For function return types it’s essentially
unknown, notundefined, and doing as suggested here would almost certainly break a bunch of existing code. What’s the return type of a function which matches both() => voidand() => {a: string}? It certainly isn’tnever. I’d say it’s{a: string}, bolstering theunknowninterpretation. Indeed I’d rather see a suggestion thatvoidshould be given consistentunknownsemantics instead of having anything to do withundefined, but that would break a lot of code also.The current behavior has to be intentional though, so whatever it is, it’s not a bug.