Skip to content

UnionToTuple type returns "inverted" tuple in TSGO compared to TypeScript 5.8.3 and gives type error #787

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

Closed
alexwork1611 opened this issue Apr 10, 2025 · 8 comments

Comments

@alexwork1611
Copy link

Hello,

This will need a little investigation (learning the type-fest package types), but I tried running TSGO in my current project and got some errors. Basically, type-fest has a UnionToTuple type and TSGO inverts the tuple values and gives an error. TSGO successfully extracts the union values and makes them into a tuple, but reversed compared to TypeScript 5.8.3.

Testable repo: https://github.com/alexwork1611/tsgo-union-to-tuple.

Hope it helps.

Thanks!

@alexwork1611 alexwork1611 changed the title UnionToTuple type returns "inverted" tuple compared to TypeScript 5.8.3 UnionToTuple type returns "inverted" tuple in TSGO compared to TypeScript 5.8.3 and gives type error Apr 10, 2025
@jakebailey
Copy link
Member

jakebailey commented Apr 10, 2025

Union ordering is undefined, determined only by the implementation details of the checker. The Go code isn't the same as the previous compiler (in order to handle concurrency) and uses a different but deterministic sort order, intentionally. Anything like "union to tuple" is going to behave differently.

@alexwork1611
Copy link
Author

Union ordering is undefined, determined only by the implementation details of the checker. The Go code isn't the same as the previous compiler (in order to handle concurrency) and uses a different but deterministic sort order, intentionally. Anything like "union to tuple" is going to behave differently.

Thanks for your answer. Shouldn't this be something that's standardized, though?

@jakebailey
Copy link
Member

What does "this" refer to, and what do you mean by "standardized"?

@alexwork1611
Copy link
Author

Good clarifying question. "This" refers to the way unions are sorted. "Standardized" refers to the idea that the two compilers should be intentionally designed to have matching union element sorting.

@jakebailey
Copy link
Member

They can't be; the old method was dependent on the order of files and the order that the checker walks everything. There was no "design", per se.

In the new compiler, we check files concurrently, which means we are going to be doing everything in entirely different orders, have errors that change each time the code is checked, etc, if we aren't careful. Hence, we have more strictly defined ordering to not be in terms of type IDs.

The ordering calculation is not free; it's not good for perf in the old codebase: microsoft/TypeScript#61399

@jakebailey
Copy link
Member

I'll note that it's always been dubious to depend on union order for anything; simple changes like swapping the order of two declarations in the same file, sorting your imports, etc, could all affect the behavior, which isn't great.

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Apr 10, 2025

We tried our best to tell people not to do this, but some folks are very determined to do dangerous things.

See also

microsoft/TypeScript#13298 (comment)

microsoft/TypeScript#13298 (comment)

@alexwork1611
Copy link
Author

Thank you so much, @RyanCavanaugh and @jakebailey. I refactored my code and I am not using the UnionToTuple type anymore.

The reason why I went for that is because I wanted to enforce the my types into my runtime, but I was able to come up with an alternative. Here is the before and after (for one of the places that were giving me errors because of the tuple elements order):

Before:

Image

After:

Image

Here are the UserRole definitions:

Image

I hope the images above provide insight into my thinking and I hope you can empathize with me not knowing the things discussed in the awesome PR mentioned by @jakebailey and @RyanCavanaugh's reply above.

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants