swagger-typescript-api icon indicating copy to clipboard operation
swagger-typescript-api copied to clipboard

Omit readonly properties from PATCH requestContent

Open rcbevans opened this issue 1 year ago • 4 comments

If a schema is referenced as the requestContent to an API, the generated RequestBody should omit readonly properties.

Given a user:

export interface User {
  readonly id: number
  name: string
  readonly email: string
}

When this type is referenced to be the input to a PATCH request, the input argument should omit readonly properties.

It should be possible to do some Typescript magic to strip readonly properties, like mentioned in https://stackoverflow.com/a/49579497/2240706.

type IfEquals<X, Y, A=X, B=never> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? A : B;

type WritableKeys<T> = {
  [P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
}[keyof T];

type ReadonlyKeys<T> = {
  [P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
}[keyof T];

type OmitReadonly<T> = Pick<T, WritableKeys<T>>; 

It would then be a case of updating the generated code to declare the argument as OmitReadonly<ReferencedType>

rcbevans avatar Dec 07 '22 07:12 rcbevans

Or a oneliner mentioned elsewhere also works:

type Writable<T> = Pick<T, {
  [P in keyof T]-?: (<U>() => U extends { [Q in P]: T[P] } ? 1 : 2) extends
  (<U>() => U extends { -readonly [Q in P]: T[P] } ? 1 : 2) ? P : never;
}[keyof T]>;

rcbevans avatar Dec 07 '22 08:12 rcbevans

Yes, this seems like a good addition. I also just encoutered this issue when trying to call a "create" method, where the generated client wants me to define the id when the webservice will do this offcourse.

Fixed it by adding a little bit of wrapping code and "dirty" casting:

  public async createWebhook(config: Writable<BookeoWebhook>) {
    await this.client.webhooks.webhooksCreate(config as BookeoWebhook);
  }

Nickman87 avatar Jan 05 '23 15:01 Nickman87

Would these one-liners handle types with non-readonly properties that are objects containing readonly properties?

For instance an endpoint for creating a batch collection of entities at one time:

MyBatch {
  readonly id: number
  entries: Array<{
    readonly id: number
    foo: string
  }>
}

slifty avatar Jan 24 '24 03:01 slifty