Skip to content

[BUG] [TypeScript-Axios] invalid code generation of anyOf #12432

Open

Description

@simllll

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

With the latest master branch, the following spec does generate the wrong code.

upgradeTo:
                                    anyOf: [{properties: {purchasedPackageId: {$ref: '#/components/schemas/APITypeObjectId_APIObjectType.PurchasedPackage_'}, mode: {type: string, enum: [purchasedPackage], nullable: false}}, required: [purchasedPackageId, mode], type: object}, {properties: {packageId: {$ref: '#/components/schemas/APITypeObjectId_APIObjectType.BuyablePackage_'}, mode: {type: string, enum: [package], nullable: false}}, required: [packageId, mode], type: object}]
                                

What it should be (this is the original defiinitoin on our side)
image

But what it does:
image

so it's not purchasedPackageId OR packageId.. it is an AND.

It's the same if we use it without the "mode" paramter, then it's just merged into one (so also purchasedPackageId and packageId is required, instead of an OR).

openapi-generator version

6.0.0 - latest master snapshot
did work with 5.x

OpenAPI declaration file content or url

Activity

  1. simllll commented on May 23, 2022

    @simllll
    Author

    Update: it "works" in earlier versions only because it's generated to a generic "object":
    image

  2. spacether commented on Jun 16, 2022

    @spacether
    Contributor

    What generator are you using?

  3. simllll commented on Jun 16, 2022

    @simllll
    Author

    axios-typescript

    That's the command line:

    openapi-generator-cli generate -t openapi-template -p apiPackage=apipkg -p modelPackage=modelPkg -p withSeparateModelsAndApi=true -p modelPropertyNaming=original -p supportsES6=true -i ../../services/admin-api/dist/swagger/swagger.yaml -g typescript-axios -o src/api-client

  4. ikopysov commented on Sep 7, 2022

    @ikopysov

    Can this issue be renamed to avoid confusion? There are multiple clients with this issue and I belive all of them should be fixed individually.

    This can be renamed to

    [BUG] [TypeScript-Axios] Invalid code generation of "anyOf"

    (most used in the issues page)
    or

    [BUG] [TypeScript] [Axios] Invalid code generation of "anyOf"

    (kind of easier to find for axios users, but harder for TypeScript users)

  5. 123FLO321 commented on Sep 8, 2022

    @123FLO321

    I am pretty sure that this issue affects all typescript generators.

  6. changed the title [-][BUG] invalid code generation of anyOf[/-] [+][BUG] [TypeScript-Axios] invalid code generation of anyOf[/+] on Sep 8, 2022
  7. bintoll commented on Sep 21, 2022

    @bintoll

    I also face this issue. The generated code is invalid with anyOf

  8. vpishuk commented on Dec 11, 2022

    @vpishuk

    I have the same issue with this generator.
    Any of generates this file:

    
    
    // May contain unused imports in some cases
    // @ts-ignore
    import { TIncludedItemAnyOf } from './tincluded-item-any-of';
    // May contain unused imports in some cases
    // @ts-ignore
    import { TIncludedItemAnyOf1 } from './tincluded-item-any-of1';
    // May contain unused imports in some cases
    // @ts-ignore
    import { TIncludedItemAnyOf2 } from './tincluded-item-any-of2';
    // May contain unused imports in some cases
    // @ts-ignore
    import { TIncludedItemAnyOf3 } from './tincluded-item-any-of3';
    // May contain unused imports in some cases
    // @ts-ignore
    import { TIncludedItemAnyOf3Attributes } from './tincluded-item-any-of3-attributes';
    
    /**
     * 
     * @export
     * @interface TIncludedItem
     */
    export interface TIncludedItem {
        /**
         * 
         * @type {string}
         * @memberof TIncludedItem
         */
        'type': TIncludedItemTypeEnum;
        /**
         * 
         * @type {string}
         * @memberof TIncludedItem
         */
        'uid'?: string;
        /**
         * 
         * @type {TIncludedItemAnyOf3Attributes}
         * @memberof TIncludedItem
         */
        'attributes'?: TIncludedItemAnyOf3Attributes;
    }
    
    export const TIncludedItemTypeEnum = {
        Set: 'set'
    } as const;
    
    export type TIncludedItemTypeEnum = typeof TIncludedItemTypeEnum[keyof typeof TIncludedItemTypeEnum];
    
    

    You can try to use oneOf as a workaround. It will work in the same way, but slightly slower.

  9. vpishuk commented on Dec 11, 2022

    @vpishuk

    I mad an MR to fix this issue.
    #14241

  10. Naktibalda commented on Jul 24, 2023

    @Naktibalda
    Contributor

    I noticed that anyOf generator fails in 2 different ways:

    Component:
      anyOf:
        - $ref: "#/components/schemas/Component1"
        - $ref: "#/components/schemas/Component2"

    generates empty interface:

    export interface Component {
    }
    Component:
      type: object
      additionalProperties:
        anyOf:
          - $ref: "#/components/schemas/Component1"
          - $ref: "#/components/schemas/Component2"

    combines all properties to single interface as described in original issue.

  11. Naktibalda commented on Jul 25, 2023

    @Naktibalda
    Contributor

    I changed all anyOf keywords tooneOf in my specification and openapi-generator produced expected types.

    export type Component = Component1 | Component2;
  12. binhtran04 commented on Sep 26, 2023

    @binhtran04

    I changed all anyOf keywords tooneOf in my specification and openapi-generator produced expected types.

    export type Component = Component1 | Component2;

    I have the same issue:
    anyOf generates an empty interface, while oneOf correctly generates a Union

    Not sure if it's safe to change all anyOf to oneOf

  13. lfals commented on Nov 12, 2026

    @lfals

    We encountered the empty-interface variant of this issue while evaluating typescript-axios for LibreSign.

    With OpenAPI Generator 7.15.0 and 7.27.0, using useSingleRequestParameter=true, this schema from our OpenAPI contract generates an empty interface:

    EffectivePolicyValue:
      nullable: true
      anyOf:
        - type: boolean
        - type: integer
          format: int64
        - type: number
          format: double
        - type: string
        - type: object
          additionalProperties:
            type: object

    Actual output:

    export interface EffectivePolicyValue {}

    Consequently, this invalid value compiles under strict TypeScript:

    const value: EffectivePolicyValue = ['not a policy value'];

    At minimum, the generated type should preserve the declared alternatives and reject arrays, instead of widening the model to an empty interface.

    We also tested replacing anyOf with oneOf in a disposable generator-input copy only. That generates:

    export type EffectivePolicyValue =
      | boolean
      | number
      | string
      | { [key: string]: object };

    This rejects the invalid array, but is not a contract-equivalent workaround: integer and number overlap, whereas oneOf requires exactly one matching alternative. The generated union also excludes null; the intended nullability and its correct OpenAPI representation need to be covered explicitly by the regression tests.

    Related work we found:

    Our reproducible evaluation is available in LibreSign/libresign#9437. We have reproduced this on the released versions above, but have not yet tested the current upstream master or those PR branches against our contract.

    We would like to investigate an upstream Axios fix, with regression tests for mixed primitive/object alternatives and nullability, potentially using #25394 as a reference. Would you prefer this work to remain tracked here, or should we open a separate issue for this specific case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions