-
-
Notifications
You must be signed in to change notification settings - Fork 532
Empty object inside of allOf creates Record<string, never> in a type intersection #1520
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
Comments
Thanks so much for writing this up. As you’ve probably seen in other issues, there can be interesting challenges presented with complex schema composition, especially with how TypeScript handles unions. While in some instances it’s better to just make minor schema adjustments for better TS output, I agree in this scenario, I can’t think of any reason why a person would want |
To give some context, this schema is commonly used with Java when the code should be generated from the OpenAPI spec. This is a way to describe inheritance. |
This happens any time I have an object represented like this:
where the type is object/null. |
I'd just like to note that the existing behaviour is actually consistent with openapi, only that openapi-typescript (as opposed to openapi) defaults to The openapi-typescript documentation is quite clear about the effect of that default behaviour - which aligns with openapi's behaviour when You can also provide the --additionalProperties=true to get the same default behaviour in openapi-typescript as in openapi. |
@drwpow It looks like the reason for defaulting
The current behaviour is consistent with openapi as long as the default is type: object
additionalProperties: false |
Description
I've decided to make it an issue mostly in case someone else is about to spend multiple hours figuring out what's wrong. That's why I'm going to be a little verbose - existing issues (#1474) are mostly tangentially related to the root cause, and I could have really used a description like this five hours ago.
If there's an object with no properties in the schema, it will get converted to
Record<string, never>
- this is the most sensible way to represent an empty object in TS. However, when such object is used inallOf
, it is put along other object definitions in a TS type intersection. The way it is interpreted, it is combining other object types with an object that has all possible keys defined as invalid.Why would you put an object with no properties inside of an
allOf
? Beats me, but I've seen that pattern before - my best guess is that it is a common way of thinking about inheritance (baseRequest -> specificRequest even if the requests have nothing in common) or some common tooling works this way.Possible solutions
I ended up just running
openapi-typescript
with the--empty-objects-unknown
CLI flag - this pretty much solved it for my use case, but you lose strict typing around empty objects. You could also add any property to the empty object if you control the schema.If i had to fix it, I'd probably start with trying to omit any
Record<string, never>
in TS types intersection generation. Unfortunately I don't have space for taking a try at this and making a PR right now.Hopefully this issue will help in documenting the problem. Cheers!
Reproduction
Run with the following input:
Expected result
Checklist
npx @redocly/cli@latest lint
)The text was updated successfully, but these errors were encountered: