openapi-ts / openapi-typescript

Generate TypeScript types from OpenAPI 3 specs
https://openapi-ts.dev
MIT License
5.47k stars 450 forks source link

Enhancing openapi-typescript for Improved Type Safety: Generating Arrays from Enum Definitions #1616

Open nakamurau1 opened 4 months ago

nakamurau1 commented 4 months ago

Description

I'm utilizing openapi-typescript to enhance API type safety. However, when parsing parameters using user-defined type guards, it's necessary to validate the elements of a Union type, requiring an array of Enum values. Currently, openapi-typescript only generates Union types, necessitating manual array definition, which introduces redundancy.

Proposal

I propose adding an option to openapi-typescript output to generate an array of Enum values. This would allow for the simultaneous generation of Union types and arrays, improving type safety and reducing code redundancy. For instance, consider the following option:

// Generated type definitions
type SortKey = 'id' | 'name' | 'cost';
// Proposed array
const sortKeys: SortKey[] = ['id', 'name', 'cost'];

Checklist

luchsamapparat commented 4 months ago

That would be very helpful!

We validate our forms with Zod to ensure that the form values match the OpenAPI spec. If the spec provides an enum with valid values, I want to pass those values to z.enum(...) to make sure that a valid value has been selected.

drwpow commented 4 months ago

I’d be open to this! While it’s still a library goal to have no runtime, technically TypeScript enums do have a runtime, so that line has been crossed already, though we do want to be reserved in what we generate (because this library tries to steer away from runtime codegen).

If anyone wants to open a PR for this, I’d like to see:

  1. The original types have the full path, e.g. const sortKeys: components["schemas"]["SortKey"][] = […]
  2. It’s behind a CLI flag (not default behavior)
  3. Lots and lots of tests 😄 (including tests that make sure that things like components["schemas"]["00-illegal-js.key"] can generate a valid JS identifier

If all 3 criteria are satisfied, happy to ship it 🙂. Just note that the current main is for the upcoming 7.x release, so if you’d like this on 6.x, base that off the 6.x branch (though a 7.0 release candidate will happen very soon, promise 😅)

luchsamapparat commented 3 months ago

I started working on it and managed to emit this in packages/openapi-typescript/test/fixtures/redocly/output/b.ts for the gender enum property in openapi/b.yaml

export const personGenderValues: components["schemas"]["person"]["gender"][] = ["male", "female", "unknown"];

I also put it behind an optional CLI flag:

  --enumValues               Export union values as arrays

Not sure about the naming and description though.

I'll create a PR next week, but I have to clean up my code first and figure add tests for it.

luchsamapparat commented 3 months ago

@drwpow I've created a PR for this: #1661

I used the enum tests as a template for testing this feature.

Also, I'm not sure about the flag's name and description and am open to suggestions for better wording.

borzaka commented 2 months ago

It would be nice to backport this to 6.x

drwpow commented 2 months ago

It would be nice to backport this to 6.x

Unfortunately I do not have time in the immediate future to add this, but I would love a PR if someone else is able to!

ericljiang commented 1 month ago

Does the new --enum-values flag work for unions too or just enums? It works when I use the --enum flag but without it, running openapi-typescript just hangs and never completes.