Skip to content

Advanced required enforcement for allOf + required case #657

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
gwre-ivan opened this issue Jun 17, 2021 · 4 comments · Fixed by #1027
Closed

Advanced required enforcement for allOf + required case #657

gwre-ivan opened this issue Jun 17, 2021 · 4 comments · Fixed by #1027

Comments

@gwre-ivan
Copy link

gwre-ivan commented Jun 17, 2021

We have an OpenAPI schema where we combine allOf with required in the way that we enforce some attributes defined by allOf to be required, something along these lines:

SomeEntity:
  required:
    - name
  allOf:
    - "$ref": "#/definitions/l10nName"
    - ...something else...

In this case name is defined in l10nName subschema and we enforce it to be required for SomeEntity. The generated code, however, does not take that into account, generating code with name property being optional.

This is something that still could be expressed via TypeScript as something like:

SomeEntity_raw: <whatever definition is being generated right now>,
SomeEntity: SomeEntity_raw & Required<Pick<SomeEntity_raw, "name">>,

What do you think? It seems to be relatively simple to detect with something like "if property is in required, but not explicitly defined in properties on current type, generate enforcing wrapper"

@drwpow
Copy link
Contributor

drwpow commented Jun 26, 2021

Thanks for suggesting! There’s actually an open PR that may solve this: #586. But I think it’s something we can add. But it’s surprisingly not “relatively simple” especially with remote schemas 🙂

@akornatskyy
Copy link

A bit more examples here.

@Swiftwork
Copy link
Contributor

@drwpow with the large rewrite you did here #968 maybe this issue can be looked at again. I was wondering if it wouldn't be wiser (if possible) to dereference schema objects in allOf and merge them all together in a new type in an additive manner creating a final schema object with required properties.

@Swiftwork
Copy link
Contributor

Swiftwork commented Jan 21, 2023

Maybe a less invasive solution to specifically this issue would be to decorate the final type with a utility class based on the required sibling property.

User:
  required:
    - id
    - name
  allOf:
    - $ref: '#/components/schemas/UserProperties'
    - type: object
      properties:
        photo: string
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

export interface components {
  schemas: {
    User: WithRequired<components["schemas"]["UserProperties"] &
    {
      photo?: string;
    }, 'id' | 'name'>;
  }
}

This would support OpenAPI version 3.1 but not 3.0 which still needs the required statement to be nested:

User:
  allOf:
    - $ref: '#/components/schemas/UserProperties'
    - type: object
      properties:
        photo: string
    - type: object
      required:
        - id
        - name

Currently, the code above generates the broken type:

export interface components {
  schemas: {
    User: components["schemas"]["UserProperties"] &
    {
      photo?: string;
    } & Record<string, never>;
  }
}

Swiftwork added a commit to Swiftwork/fork-openapi-typescript that referenced this issue Jan 21, 2023
drwpow pushed a commit that referenced this issue Feb 23, 2023
* feat: add with required utility to enforce properties of allOf

Resolves #657

* style: corrected lint issues

* test: updated snapshots
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants