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

Case conversion (e.g. snake_case to camelCase) #924

Closed
anguspmitchell opened this issue Jul 20, 2022 · 6 comments
Closed

Case conversion (e.g. snake_case to camelCase) #924

anguspmitchell opened this issue Jul 20, 2022 · 6 comments

Comments

@anguspmitchell
Copy link

anguspmitchell commented Jul 20, 2022

Has anyone additionally converted their OpenAPI spec's case from, e.g., snake_case to camelCase?

I tried using the programmatic version (const output = await openapiTS("https://myurl.com/v1/openapi.yaml");) but was getting an error (0 , _openapiTypescript.default) is not a function. I think that may be related to this issue: #888

I tried copy and pasting this solution - https://stackoverflow.com/a/65642944/5469472 - but it wasn't handling a nested attribute correctly (technically, an attribute whose type was list of another attribute)

@anguspmitchell
Copy link
Author

Edit: For now, I found that the type-fest package provides this functionality, although there is the extra step of keeping this in sync with the autogenerated file from openapi-typescript

import { components } from "@/types/autogen-api-schema";
import type { CamelCasedPropertiesDeep } from "type-fest";

export type ETaskGET = CamelCasedPropertiesDeep<
  components["schemas"]["ETaskGET"]
>;```

@anguspmitchell
Copy link
Author

If anyone else comes across this, here's the scheme that I'm using:

npx openapi-typescript http://localhost:8000/openapi.json --output src/types/autogen-api-schema.ts

echo 'import { components } from "@/types/autogen-api-schema";' > src/types/api-schema.ts
echo 'import type { CamelCasedPropertiesDeep } from "type-fest";' >> src/types/api-schema.ts
echo '' >> src/types/api-schema.ts

sed '/export interface components/,/export interface operations/!d' < src/types/autogen-api-schema.ts | `# throw out everything that isn't in the components section` \
    sed -nE '/    .+: {$/p' |  `# filter down to rows that are one level deep are the beginning of a type def` \
    grep -Eo '[A-Za-z_0-9]+' | `# strip out spaces, ':', and '{'` \
    sed 's/.*/export type & = CamelCasedPropertiesDeep<components["schemas"]["&"]>;/' `# create the TS alias` \
    >> src/types/api-schema.ts

@drwpow
Copy link
Contributor

drwpow commented Aug 6, 2022

Good luck with this! This is quite a can of worms and is something most people just leave as-is. snake_case is perfectly valid JS and converting to camelCase should be seen as purely a stylistic choice (I personally never understand linting rules that discourage snake_case).

Renaming things can often result in breakage as you found out, which is also why this library uses the components['schemas']['Foo']['Bar'] syntax—to allow TypeScript to handle literally any valid name possible.

@drwpow
Copy link
Contributor

drwpow commented Aug 6, 2022

I’m going to close this issue as this isn’t an issue with this library specifically. But thank you for posting! People will always be able to find this through searching (even through Google—more so than you’d think!)

@drwpow drwpow closed this as completed Aug 6, 2022
@rdsedmundo
Copy link

I was also looking for this, as using camelCase is the defacto standard way in JS code (even though at the API layer it gets converted to snake_case). I expected to be able to do this using the transform function but it's fairly limited in functionality as far as I can tell.

@bapjiws
Copy link

bapjiws commented Mar 7, 2024

@anguspmitchell Thanks for you solution and mentioning the type-fest project, CamelCasedPropertiesDeep is a life saver! I very much agree with the snake_case arguments, but our entire project already relies on camelCase 😄

What you also can do instead of creating a new file with the bash magic is a wrapper type:

type SchemaByName<S extends keyof components['schemas']> = CamelCasedPropertiesDeep<components['schemas'][S]>

This way, you would have completion on all of your schema names and only have one file generated by openapi-typescript.

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

4 participants