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

Co-dependency of variables destructured from union types is lost unless used in control-flow statements #55344

Open
jeengbe opened this issue Aug 12, 2023 · 2 comments
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Milestone

Comments

@jeengbe
Copy link

jeengbe commented Aug 12, 2023

🔎 Search Terms

destructuring union type tuple

Please expand this list or edit the title with a better-fitting description.

🕗 Version & Regression Information

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

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.1.6#code/CYUwxgNghgTiAEYD2A7AzgF3gNyhAjAFzxxTCoQCe8A2gORR0A08DdAuvAD4khkXV6AI2asR7ANwAoAPQz4CxUoUA9APxSpydFhrZ8LbACZOAXhx580rakwWIR+Ob0GcJ+FDSJbGaXKXqsvIAkl4oSPAQqADmIDC8-ChUtABEUCksaSmcPKTkSYIpQhnwRdlSQA

💻 Code

declare const val1: readonly ['a', 'a'] | readonly ['b', 'b'];
//            ^?

const [v1, v2] = val1;

const val2 = [v1, v2] as const;
//    ^?
// Is no longer readonly ["a", "a"] | readonly ["b", "b"]

🙁 Actual behavior

When destructuring a variable readonly ["a", "a"] | readonly ["b", "b"] into [v1, v2] = val, the compiler is sophisticated enough to retain the dependency of the two when either is used in either an if or even a switch statement:

if(v1 === 'a') {
  v2;
// ^?
// TS is smart enough to know that this is "a"
}

When put back together, however, that dependency is lost. For:

declare const val1: readonly ['a', 'a'] | readonly ['b', 'b'];

const [v1, v2] = val1;

const val2 = [v1, v2] as const;

val1 and val2 should be identical, however, val2 is readonly ["a" | "b", "a" | "b"]. Note that this not only applies to tuples, but de- and restructured objects as well.


See this real example of a legitimate use-case and how this affects the code.

🙂 Expected behavior

Just like with

if(v1 === 'a') {
  v2;
// ^?
// TS is smart enough to know that this is "a"
}

the compiler should figure out that v1 and v2 depend on each other when combining them with e.g. [v1, v2] and create an according union type of tuples instead of a single tuple with union type members.

@fatcerberus
Copy link

See #55257 and ultimately, #30581. The correlation between the types isn't currently tracked beyond what's needed to support discriminated union narrowing.

@jeengbe
Copy link
Author

jeengbe commented Aug 12, 2023

That's right, thank you for the links! I didn't know about those.

The patch could, however, be extended to cover cases like these without immediately solving the underlying problem.

@RyanCavanaugh RyanCavanaugh added Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases labels Aug 14, 2023
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Aug 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Projects
None yet
Development

No branches or pull requests

3 participants