Skip to content

oneOf parent with sibling properties is ignored; base fields only appear on union members when using allOf on each variant #401

Description

@paulnaber

Description

When a schema combines oneOf with sibling properties, ng-openapi-gen emits only a TypeScript union of the referenced types. The sibling properties are not reflected on the generated type.

When the same base fields are modeled with a separate schema and each variant uses allOf to extend it, generation works as expected (BaseDto & { ... } per variant). I want to confirm whether the first pattern is intentionally unsupported and whether the allOf approach is the recommended workaround.

I think it used to work with older versions but I could not confirm it.

Environment

ng-openapi-gen: 1.0.4, 1.0.5
OpenAPI: 3.0.x

Current behavior
Spec (simplified):

ResourceBaseDto:
  type: object
  properties:
    resourceId:
      type: integer
      format: int64
    resourceType:
      $ref: '#/components/schemas/ResourceType'
    resourceName:
      type: string
FirmwareResourceDto:
  type: object
  properties:
    file:
      type: string
ResourceDto:
  description: Polymorphic resource
  oneOf:
    - $ref: '#/components/schemas/FirmwareResourceDto'
    - $ref: '#/components/schemas/OtherResourceDto'
  properties:
    resourceId:
      type: integer
      format: int64
    resourceType:
      $ref: '#/components/schemas/ResourceType'
    resourceName:
      type: string
Generated resource-dto.ts:

export type ResourceDto = FirmwareResourceDto | OtherResourceDto;
Common fields (resourceId, resourceType, etc.) are not on ResourceDto. Subtype files also only contain their own fields unless allOf is used

Expected behavior (question)

What is the intended way to model “polymorphic object with shared base fields” so that:

ResourceDto is a union of variants, and
consumers can access shared fields (e.g. resource.resourceId) with correct typing?

Merge sibling properties into the union (e.g. ResourceBaseDto & (A | B)), or include the shared properties within the variants.

Workaround that works today

Split base fields into ResourceBaseDto and reference it from each variant:

FirmwareResourceDto:
  allOf:
    - $ref: '#/components/schemas/ResourceBaseDto'
  type: object
  properties:
    file:
      type: string
ResourceDto:
  oneOf:
    - $ref: '#/components/schemas/FirmwareResourceDto'
    - $ref: '#/components/schemas/OtherResourceDto'

Generated:

export type FirmwareResourceDto = ResourceBaseDto & { file?: string };
export type ResourceDto = FirmwareResourceDto | OtherResourceDto;
This satisfies our use case because every union member includes ResourceBaseDto, so resourceId is accessible on ResourceDto.

Impact

We generate our openapi yml direcly from the backend. The extra BaseDto has to be implemented within the backend code.

Questions

  1. Is oneOf + sibling properties on the same schema object supported? Was it supported once?
  2. Is allOf on each oneOf branch the recommended pattern for shared properties in OpenAPI 3.0?
  3. Would it make sense to emit export type ResourceDto = ResourceBaseDto & (A | B) when both oneOf and sibling properties are present, or is that considered invalid input?

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions