openapi-ts icon indicating copy to clipboard operation
openapi-ts copied to clipboard

Generate array types as readonly

Open phjardas opened this issue 10 months ago • 3 comments

Description

When generating TypeScript type definitions, it would be nice to have an option to generate all array types as readonly, either with ReadonlyArray<T> or readonly T[]. IMHO this should even be the default behavior, because it enhances code safety. These are value objects and should be generally immutable.

phjardas avatar Jan 29 '25 18:01 phjardas

To extend this: Right now it seems that only primitive types are getting prefixed with readonly if marked as such in the openapi definition. However $ref propertys are not marked as readonly in the generated types, even when marked as such in the definition.

MGRatEJOT avatar Apr 04 '25 08:04 MGRatEJOT

@MGRatEJOT Can you give an example? I'm not sure I'm following the problem in your instance

mrlubos avatar Apr 04 '25 09:04 mrlubos

Sorry for the delay.

Here is an example:

openapi: 3.0.4
info:
  title: TEST_API
  version: v1
components:
  schemas:
    TestObject:
      type: object
      properties:
        idProp:
          allOf:
            - $ref: "#/components/schemas/TestId"
          readOnly: true
        enumProp:
          allOf:
            - $ref: "#/components/schemas/TestEnum"
          readOnly: true
        stringProp:
          type: string
          readOnly: true
      additionalProperties: false
    TestId:
      type: string
      additionalProperties: false
    TestEnum:
      enum:
        - TestEnumValue1
        - TestEnumValue2
      type: string

generates

// This file is auto-generated by @hey-api/openapi-ts

export type TestObject = {
    idProp?: TestId;
    enumProp?: TestEnum;
    readonly stringProp?: string;
};

export type TestObjectMutable = {
    idProp?: TestId;
    enumProp?: TestEnum;
};

export type TestId = string;

export type TestEnum = 'TestEnumValue1' | 'TestEnumValue2';

export const TestEnum = {
    TEST_ENUM_VALUE1: 'TestEnumValue1',
    TEST_ENUM_VALUE2: 'TestEnumValue2'
} as const;

export type ClientOptions = {
    baseUrl: `${string}://${string}` | (string & {});
};

so only the plain string property is marked as readonly, but not the $ref types.

I also see that the mutable version does not include the stringProp at all. Is that the expected behaviour?

MGRatEJOT avatar Apr 23 '25 07:04 MGRatEJOT