Skip to content

[Bug]: TypeScript parameters preset emits non-compiling code (query-param casing + missing deserializeUrl for path-only params) #372

Description

@ALagoni97

Description

Generating a TypeScript client from an OpenAPI spec produces parameters files that fail tsc. Generation reports zero errors; the breakage only appears when the generated package is built. Two independent defects in the parameters preset:

1. serializeQueryParameters() uses the original parameter name as the property accessor
Fields are constrained to camelCase (skip), but the query serializer references this.Skip (original spec casing). Any query parameter not already camelCase (Skip, Take, ReferenceId, Public, …) fails. The path-parameter serializer does not have this bug — it correctly uses the constrained name.

TS2551: Property 'Skip' does not exist on type 'GetItemParameters'. Did you mean 'skip'?

2. fromUrl() always calls instance.deserializeUrl(url), but deserializeUrl is only generated when the class has query parameters.
A parameters class with only path parameters omits the method but still calls it.

TS2551: Property 'deserializeUrl' does not exist on type 'GetDocParameters'. Did you mean 'serializeUrl'?

Environment

  • CLI Version: 0.72.0 (latest)
  • Node Version: v22.14.0
  • OS: Windows 11

Minimal Reproduction

codegen.ts

import { TheCodegenConfiguration } from '@the-codegen-project/cli'

const config: TheCodegenConfiguration = {
  inputType: 'openapi',
  inputPath: './input.openapi.json',
  language: 'typescript',
  generators: [{ preset: 'parameters', outputPath: './src/parameters', serializationType: 'json' }],
}

export default config

input.openapi.json

{
  "openapi": "3.1.1",
  "info": { "title": "Params repro", "version": "1.0.0" },
  "paths": {
    "/items/{itemId}": {
      "get": {
        "operationId": "getItem",
        "parameters": [
          { "name": "itemId", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "Skip", "in": "query", "schema": { "type": ["integer", "string"] } }
        ],
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/docs/{docId}": {
      "get": {
        "operationId": "getDoc",
        "parameters": [
          { "name": "docId", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "OK" } }
      }
    }
  }
}

Command

the-codegen-project generate && tsc --noEmit

Actual Output

GetItemParameters.ts (query serializer references the raw name):

private _skip?: string | number;
get skip(): string | number | undefined { return this._skip; }
// ...
serializeQueryParameters(): URLSearchParams {
  const params = new URLSearchParams();
  if (this.Skip !== undefined && this.Skip !== null) {   // this.Skip does not exist
    params.append('Skip', encodeURIComponent(String(this.Skip)));
  }
  return params;
}

GetDocParameters.ts (path-only class; deserializeUrl never generated):

static fromUrl(url: string, basePath: string): GetDocParameters {
  const pathParams = this.extractPathParameters(url, basePath);
  const instance = new GetDocParameters({ docId: pathParams.docId });
  instance.deserializeUrl(url);   // method not generated for path-only classes
  return instance;
}

Expected Output

  1. The query serializer should use the constrained accessor this.skip while keeping the wire key 'Skip':
if (this.skip !== undefined && this.skip !== null) {
  params.append('Skip', encodeURIComponent(String(this.skip)));
}
  1. deserializeUrl should always be generated (a no-op when there are no query parameters), or fromUrl should not call it for path-only classes.

Additional Context

  • Discovered while publishing a real client; the publish pipeline runs npm run build (tsc) before npm publish, so these tsc errors abort publishing.
  • Every parameters file in a real spec hits defect 2 at the fromUrl call site; PascalCase-heavy query specs additionally hit defect 1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions