Hoi hoi!
I'm @nyaomaru, a frontend engineer who thought OpenAPI codegen would make API clients easier, but somehow ended up lost in a forest of ge...
For further actions, you may consider blocking this person and/or reporting abuse
Very useful ππ»
Thx! πΈ
You are welcome π!
so useful :))
Thx! πΈ
Amazing article.
Adopted hey-api for about 2 years now!
The only thing that bother me alot is the fact that it turns | null properties into unknown
Ex: if a property type is "string | null", it turns it into "unknow"
Wonder if you have the same error.
Reached out for the maintainer multiple times but to no avail.
Thank you
Thank you for your comment and sharing this!
I checked my generated files again, and in this project I donβt seem to have the same issue.
My schema is OpenAPI 3.0.3 generated by drf-spectacular, and nullable string fields are represented with nullable: true.
For example:
is generated as:
I also checked the generated type file, and
string | nullappears correctly in many places.There are some
unknowntypes in my generated output, but they seem to come from different schema shapes, such asadditionalProperties,items: {}, or empty schemas like:So at least in my case,
string | nullitself is not being converted tounknown. πΏI wonder if the issue may depend on the OpenAPI schema format, for example OpenAPI 3.1 style:
or maybe a specific combination of $ref, nullable, and the hey-api version difference. π€
Small update: I also tried the OpenAPI 3.1 style, and it seems to work fine on my side too.
So maybe the issue depends on another condition, such as an OpenAPI schema version older than 3.x, or an older hey-api version than
@hey-api/openapi-ts@0.96.1.At least with my current setup, both OpenAPI 3.0.3
nullable: trueand OpenAPI 3.1type: ["string", "null"]seem to generatestring | nullcorrectly. And if you can't generate correctly with same version, it may be a difference of setup config. π€Thank you for your answers.
I'm rather using ElysiaJS as my backend framework. It have an openapi plugin that uses Scalar under the hood.
The current openapi version of the generated doc is 3.0.3 style
but there is no $ref in the document.
@hey-api/openapi-ts package is up to date (version 0.97.3)
Maybe i configured it wrong
That makes sense. In my case, the OpenAPI schema is generated by
drf-spectacular, and it does include many$refentries undercomponents.schemas.So I think this may be an important difference:
drf-spectacular/Djangogenerates shared schemas with$refElysiaJS/Scalarseems to generate inline schemas without$refπ€I guess this is probably not controlled by
hey-apiitself.hey-apiis the consumer of the OpenAPI document, whileElysiaJS/Scalarordrf-spectacularis the producer of the OpenAPI document.No
$refdoes not automatically mean the schema is broken, but maybe the specific inline nullable shape generated byElysiaJSis causinghey-apito fall back to unknown.So my current guess is that this may be related to the OpenAPI output shape from
ElysiaJS/Scalar, rather than thehey-apiconfig itself.Hope this helps a bit! πΊ
Yes, it really helps.
I've found out that this feature is still experimental on Elysia framework.
I may have to find other ways to get a proper schema
Thank you very much!
Thanks for this amazing article!
I was actually looking for a comparison between Orval and Hey-API to share with some colleagues, so this came at the perfect time.
Personally, I think thereβs no competition: Hey-API is by far superior to any other OpenAPI client generator Iβve ever tested (and Iβve tried quite a few).
Here are a few thoughts on the points you raised:
It's worth noting that, unlike the output generated by Hey-API, this combination doesn't perform any kind of runtime validation on the payload. The client completely trusts the TypeScript types blindly (which, in my opinion, isn't the safest approach, but that's a whole different story...).
That's true, but file I/O bottlenecks can often be mitigated. If you parallelize the execution tasks, you can actually keep the generation speed quite high.
Regarding "Output Size":
We should consider that since a large portion of the output consists of TypeScript types, these are completely stripped out at runtime (e.g., in the final browser bundle). Furthermore, because the generated code repeats the exact same patterns, the gzipped size (which is what the browser actually downloads) doesn't grow linearly with the raw code size. Therefore, a massive raw output size might have a negligible impact on bundle size.
Regarding "Result Union" and Error Models:
A persistent issue that none of the generators I've tested has managed to solve is discriminating between different response schemas. When an endpoint returns a payload that could correspond to multiple success or failure states, these tools don't allow you to easily discriminate between the specific values matching the different schemas defined in the spec. Honestly, this limitation is the unique reason why I ended up writing my own.
Thanks a lot for the detailed comment! πΊ
I also took a look at your benchmark repository. Itβs interesting, although Iβd be careful about drawing strong conclusions from older versions since this space moves quite fast.
For example, Iβve already received feedback that newer versions of hey-api have improved generation speed quite a bit, and that the output structure can be customized with options like
getFilePath. Things are moving really fast.Absolutely, TypeScript types alone are not runtime validation. I agree that we still need to think carefully about runtime validation, especially at API boundaries.
I agree with your point that raw output size and actual runtime/bundle impact should be considered separately. Type-only output and gzip can make the practical impact very different from the raw generated size.
And the response schema discrimination issue is also a really interesting point. I didnβt cover it deeply in this article, but I can see why that could become a reason to build a custom solution.
Thanks again, your comment gives me several good points to revisit. π
i totally get what you mean about getting lost in the generated files. it's crucial that the output is manageable and easy to work with. at moonshift, you can quickly build a full next.js app with postgres and auth deployed in around 7 minutes. you have complete control over the code on your github. let me know if you're interested in a free run to see how it goes.
For small projects, that kind of workflow sounds very useful. But once the project becomes a large business system, generated files can easily become a forest... πΏπ³
Is Moonshift more like a boilerplate application generator?
I think it could become even more interesting if it had a strong integration story with OpenAPI codegen. Passing types from the server side to the frontend in a loosely coupled way is still a hard problem, especially in larger systems.
So if Moonshift can help with that boundary, I think there may be real demand for it. πΊ