Skip to content

Use of OneOf type causing upcasting to any #1019

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

Closed
1 task done
andyrichardson opened this issue Dec 14, 2022 · 4 comments · Fixed by #1207
Closed
1 task done

Use of OneOf type causing upcasting to any #1019

andyrichardson opened this issue Dec 14, 2022 · 4 comments · Fixed by #1207
Labels
bug Something isn't working openapi-ts Relevant to the openapi-typescript library

Comments

@andyrichardson
Copy link

Description

The OneOf function hits a call stack limit on larger unions (>8 entities).

Screenshot 2022-12-14 at 13 20 27

Name Version
openapi-typescript 6.1.0
Node.js 19.1.0
Typescript 4.9.4
OS + version macOS 13

Reproduction

Visit this sandbox

Expected result

OneOf type handles larger arguments without issue

Actual result

OneOf type exceeds call stack limit after an array of size 8.

Checklist

Notes

I've done the following as a workaround, although I suspect this will lead to type inaccuracies.

type OneOf<T extends any[]> = T[number];
@drwpow
Copy link
Contributor

drwpow commented May 14, 2023

It seems the root issue here is the OneOf<…> type inference can only handle an array of n length before becoming too complicated to evaluate. It seems to be working fine for most small numbers (~ 5 or fewer). Will investigate a fix but it may be tricky to do so because it does matter quite a bit what is being evaluated.

@sebastian-fredriksson-bernholtz

I'm not sure if it's worth the tradeoff, but I patched openapi-typescript to use union | instead of the OneOf generic type to handle this in a project of mine.

It seems like the cost of this issue might outweigh the value of being strict about excess properties.

@drwpow
Copy link
Contributor

drwpow commented May 17, 2023

You raise a good point—if this isn’t working as-is, a union would give better results.

Funny enough the reason for the OneOf type came from anyOf requiring unions to work properly (it’s hard to believe but it’s true when you dig into how TS works). And the reasoning was if oneOf used unions too, it would functionally mean anyOf and oneOf generated the same TS types, which felt wrong on principle.

But that said, in practice, these are used very differently in schemas. And even if oneOf and anyOf generated the same TS types due to quirks of how the language works, it might produce the intended types better for both scenarios (since TS unions kinda handle both).

So anyways, I’ll investigate whether or not the OneOf helper is needed for most common cases; this library got by with unions for quite a while with no complaints.

@drwpow drwpow added the openapi-ts Relevant to the openapi-typescript library label May 22, 2023
@jonajames
Copy link

Crude and horrible workaround: pass a transform option to openapiTS that turns long oneOf into anyOf.

const transform = (schema, metadata) => {
  // Workaround for https://github.com/drwpow/openapi-typescript/issues/1019
  if ("oneOf" in schema && schema.oneOf.length > 5) {
    schema.anyOf = schema.oneOf
    delete schema.oneOf
  }
}

@drwpow drwpow mentioned this issue Jul 7, 2023
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working openapi-ts Relevant to the openapi-typescript library
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants