Skip to content

fix(typescript-fetch): emit erasable syntax in the runtime template - #24575

Open
mvhenten wants to merge 1 commit into
OpenAPITools:masterfrom
mvhenten:fix/typescript-fetch-erasable-syntax
Open

fix(typescript-fetch): emit erasable syntax in the runtime template#24575
mvhenten wants to merge 1 commit into
OpenAPITools:masterfrom
mvhenten:fix/typescript-fetch-erasable-syntax

Conversation

@mvhenten

@mvhenten mvhenten commented Aug 3, 2026

Copy link
Copy Markdown

The typescript-fetch runtime template uses TypeScript constructor parameter properties in nine places. A parameter property both declares a field and assigns it, so it is not erasable syntax — it cannot be removed by stripping types.

Two consequences for generated clients:

  • Node refuses to load the generated runtime.ts at all under type stripping: SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript parameter property is not supported in strip-only mode. Since Node 24 this is the default loader for .ts files, so a generated client cannot be run without a build step.
  • tsc --erasableSyntaxOnly (TypeScript 5.8+) rejects every one of those sites with TS1294.

Separately, FetchError declares cause, which collides with Error.cause on ES2022 and later lib targets. Consumers compiling with --noImplicitOverride get TS4115. Adding an override modifier is not an option because it breaks the lib targets that predate Error.cause (TS4113) — including the generator's own default es5/es6 output. Declaring cause on a merged interface instead satisfies both.

fixes #22400
fixes #14515

Change

runtime.mustache only. Every parameter property becomes an explicit field declaration plus an assignment in the constructor body, and FetchError.cause moves to an interface declaration. Public API, field visibility and emitted JavaScript semantics are unchanged.

export class Configuration {
    private configuration: ConfigurationParameters;

    constructor(configuration: ConfigurationParameters = {}) {
        this.configuration = configuration;
    }
}

Verification

Against the regenerated samples:

  • tsc --noEmit on builds/es6-target, builds/with-npm-version, builds/prefix-parameter-interfaces and builds/without-runtime-checks — clean.
  • The same, with --target es2022 --erasableSyntaxOnly --noImplicitOverride — clean.
  • Node 24 loads builds/default/runtime.ts directly, constructs Configuration, BaseAPI, RequiredError, FetchError, ResponseError and the four ApiResponse classes, and reads back their fields. The same script against the previous output fails with SyntaxError: TypeScript parameter property is not supported in strip-only mode.

PR checklist

cc @TiFu (2017/07) @taxpon (2017/07) @sebastianhaas (2017/07) @kenisteward (2017/07) @Vrolijkx (2017/09) @macjohnny (2018/01) @topce (2018/10) @akehir (2019/07) @petejohansonxo (2019/11) @amakhrov (2020/02) @davidgamero (2022/03) @mkusaka (2022/04) @joscha (2024/10) @dennisameling (2026/02)


Summary by cubic

Emit erasable TypeScript in the typescript-fetch runtime and fix FetchError.cause compatibility. Generated clients now run with Node 24’s strip-only loader and compile with tsc --erasableSyntaxOnly.

  • Bug Fixes
    • Replaced constructor parameter properties with explicit fields and assignments; behavior and visibility unchanged.
    • Declared FetchError.cause on a merged interface to avoid TS4115/TS4113 across lib targets.
    • Regenerated samples to use the updated runtime.

Written for commit b2bd76d. Summary will update on new commits.

Review in cubic

Replace constructor parameter properties in runtime.mustache with explicit
field declarations and constructor assignments, and declare FetchError.cause
through an interface so it needs no override modifier.

fixes OpenAPITools#22400
fixes OpenAPITools#14515

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 22 files

Re-trigger cubic


// `cause` is declared through an interface so that it stays compatible with lib targets
// that already declare `Error.cause` (ES2022+) as well as the ones that do not
export interface FetchError {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this interface? if we need it, should it have a different name?

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

Labels

None yet

Projects

None yet

2 participants