Skip to content

OneOf type generating Record<string,never> despite all types defined #1277

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 of 2 tasks
mattoni opened this issue Aug 7, 2023 · 3 comments · Fixed by #1287
Closed
1 of 2 tasks

OneOf type generating Record<string,never> despite all types defined #1277

mattoni opened this issue Aug 7, 2023 · 3 comments · Fixed by #1287
Labels
bug Something isn't working good first issue Straightforward problem, solvable for first-time contributors without deep knowledge of the project openapi-ts Relevant to the openapi-typescript library PRs welcome PRs are welcome to solve this issue!

Comments

@mattoni
Copy link

mattoni commented Aug 7, 2023

Description

I have the following definition for an object:

title: StepResourceLocation
type: object
description: Either a details ID or details from where the ID is an identifier for an existing resource and a from is an identifier from a previous step in this pipeline.
oneOf:
  - title: DetailsId
    type: object
    required:
      - id
    properties:
      id:
        type: string
        description: The ID of an existing resource that exists before the pipeline is run.
  - title: DetailsFrom
    type: object
    required:
      - from
    properties:
      from:
        type: object
        description: The stage and step to report on.
        required:
          - step
        properties:
          stage:
            type: string
            description: An identifier for the stage the step being reported on resides in.
          step:
            type: string
            description: An identifier for the step to be reported on.

However, the generated type is:

    /**
     * StepResourceLocation
     * @description Either a details ID or details from where the ID is an identifier for an existing resource and a from is an identifier from a previous step in this pipeline.
     */
    ResourceLocation: Record<string, never> & OneOf<[{
      /** @description The ID of an existing resource that exists before the pipeline is run. */
      id: string;
    }, {
      /** @description The stage and step to report on. */
      from: {
        /** @description An identifier for the stage the step being reported on resides in. */
        stage?: string;
        /** @description An identifier for the step to be reported on. */
        step: string;
      };
    }]>;

I cannot figure out why it's generating Record<string, never> here. This is a pretty straightforward oneOf, and the options are being generated correctly otherwise.

Name Version
openapi-typescript 6.4.0
Node.js 19.0.0
OS + version Linux Pop!_OS 22.04 LTS

Reproduction

Run the above through openapi-typescript generator

Expected result

There should be no Record<string,never> as part of this definition.
Checklist

@mattoni mattoni added bug Something isn't working openapi-ts Relevant to the openapi-typescript library labels Aug 7, 2023
@drwpow
Copy link
Contributor

drwpow commented Aug 9, 2023

Hm yeah this definitely looks like a bug. Those types aren’t intentional.

@drwpow drwpow added PRs welcome PRs are welcome to solve this issue! good first issue Straightforward problem, solvable for first-time contributors without deep knowledge of the project labels Aug 9, 2023
@drwpow
Copy link
Contributor

drwpow commented Aug 9, 2023

Ah the Record<string, never> is from the parent object having "type": "object" but no properties or additionalProperties of its own declared. Technically-speaking this is correct since the parent schema is declaring it’s both an empty object ("type": "object" with no properties or additionalProperties) as well as oneOf the declared other types. Therefore it is a union intersection of an empty object (Record<string, never>) as well as the other child types.

The OpenAPI spec allows the use of oneOf WITHOUT having to declare a root-level "type". And I’d recommend doing this in general—if using oneOf, don’t declare a root-level type, and instead inherit one of the child types (after all, they are allowed to diverge!)

However, I can’t imagine a scenario where this is actually the intended output, so we can just fix this from happening. Though I think this wouldn’t cause any major issues and is probably ignorable, let’s just generate better types here just in case.

@mattoni
Copy link
Author

mattoni commented Aug 10, 2023

Fantastic, thank you so much and for your quick fix. Your explanation makes sense, but I think you're right, in practice this would never be the desired result and makes the intended result unavailable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Straightforward problem, solvable for first-time contributors without deep knowledge of the project openapi-ts Relevant to the openapi-typescript library PRs welcome PRs are welcome to solve this issue!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants