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

Union type to "unordered" array #57321

Closed
6 tasks done
molinch opened this issue Feb 7, 2024 · 6 comments
Closed
6 tasks done

Union type to "unordered" array #57321

molinch opened this issue Feb 7, 2024 · 6 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@molinch
Copy link

molinch commented Feb 7, 2024

πŸ” Search Terms

union type to array

βœ… Viability Checklist

⭐ Suggestion

  • This feature has been rejected several times (see: Type manipulations: union to tupleΒ #13298) due to the premise that a union type is unordered and cannot be converted into a Tuple or an Array as these have a given order.
  • While this is true the reality is that we often need to create arrays that contain all possible union type members, without caring about their positions within such arrays. Examples:
    • you want to generate all possible <option> of your <select> for all union type members, then you would most likely sort ascending anyway
    • for validation purpose with libs like zod
  • Different folks also suggested that instead of trying to get an array out of a union type, you could do the opposite: create the array of possibilities, and generate the union type out of it.
  • Unfortunately when working with schemas delivered by a backend and using tools to generate types then we gain strong guarantees but loose the ability to customize the type definition. Such type generation tools would often create union types.

Having a way to transform a union type into an "unordered" array would remove a ton of boilerplate we need to write now.

πŸ“ƒ Motivating Example

Allow iterating on union types, by transforming the union type into an array.

πŸ’» Use Cases

  • The main use case is when you are not in control of type generation, e.g. a schema delivered from a backend (OpenAPI, GraphQL, etc)
@RyanCavanaugh
Copy link
Member

I can't think of something you could do with this that you can't already do today.

"Let me do the thing I'm asking for" is not a motivating example; it's begging the question. What are you trying to do?

@molinch
Copy link
Author

molinch commented Feb 7, 2024

Thanks Ryan for the feedback. My apologies if the intent was not clear enough.
I will explain exactly our use case then.

When your backend exposes a GraphQL schema, then you can generate all the types exposed by its schema. In our case we use the Relay compiler for that purpose and it generates the TypeScript types. This gives us strong guarantees.
As such we get union types, for example we have the Language union which contains English, French, Italian or German.
Relay compiler would create:

type Language = "English" | "French" | "Italian" | "German"

We then offer all these languages into a dropdown list and the user of our application can choose one language from it.

It could be due to our lack of knowledge, I cannot be 100% sure, but right now we would create an array containing all possible languages, and we would create the dropdown entries from it. As such our code looks like:

const languages: Language[] = ["English", "French", "Italian", "German"]
// Then use languages to generate dropdown entries

If we could generate such arrays from the union type members, then this step would be eliminated.
Do you see an alternative?

@fatcerberus
Copy link

If we could generate such arrays from the union type members

So you're trying to generate a runtime-accessible array from a type definition? Yeah, that's not going to happen; it violates

This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)

You always have to do the reverse: write the array, then infer a type from it.

Playground

const languages = ["English", "French", "Italian", "German"] as const;
type Language = typeof languages[number];
//   ^?

@RyanCavanaugh
Copy link
Member

We don't generate runtime code from type information, ever - that's a key design constraint.

I think you'd be interested to read #53171 - this is the use case as far as I understand

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Declined The issue was declined as something which matches the TypeScript vision labels Feb 7, 2024
@MichalMarsalek
Copy link

MichalMarsalek commented Feb 8, 2024

You should instead modify the generator to generate the runtime array, that's what I do when generating typescript code from an OpenAPI schema.

@molinch
Copy link
Author

molinch commented Feb 8, 2024

Thanks @RyanCavanaugh and @fatcerberus you nailed it, it would be against TS goals.
@MichalMarsalek that's the direction I am heading to.

@molinch molinch closed this as completed Feb 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants