Skip to content

fix(cli): support TypeScript 7 when loading capacitor.config.ts#8534

Open
conbrad wants to merge 1 commit into
ionic-team:mainfrom
conbrad:fix/ts7-config-loading
Open

fix(cli): support TypeScript 7 when loading capacitor.config.ts#8534
conbrad wants to merge 1 commit into
ionic-team:mainfrom
conbrad:fix/ts7-config-loading

Conversation

@conbrad

@conbrad conbrad commented Jul 20, 2026

Copy link
Copy Markdown

TypeScript 7 dropped the classic compiler API (transpileModule, ModuleKind, etc.) from its default export, so requireTS's use of ts.transpileModule throws on projects with typescript@7 installed and every command that reads capacitor.config.ts fails immediately.

This change detects when that API isn't available and falls back to Node's own built-in TypeScript syntax stripping via a real dynamic import() (stable since Node 23.6, available behind --experimental-strip-types since Node 22.6) instead of transpiling the file ourselves. Falls back to a clear error if neither is available. Projects on older TypeScript versions are unaffected: the existing transpileModule path is unchanged.

Fixes #8531

Description

Change Type

  • Fix
  • Feature
  • Refactor
  • Breaking Change
  • Documentation
  • Other (CI, chores, etc.)

Rationale / Problems Fixed

TypeScript 7 dropped the classic compiler API (transpileModule, ModuleKind, etc.) from its default export: require('typescript') now only exposes version/versionMajorMinor, with the replacement living behind non-call-compatible typescript/unstable/* subpaths. requireTS in cli/src/util/node.ts calls ts.transpileModule(...) with module: ts.ModuleKind.CommonJS to transpile capacitor.config.ts on the fly, so on any project with typescript@7 installed, every command that loads the config (sync, run, copy, config, etc.) fails immediately with TypeError: Cannot read properties of undefined (reading 'CommonJS').

This PR detects when the classic compiler API isn't available and falls back to loading the config via a real dynamic import(), letting Node's own built-in TypeScript type-stripping do the work instead (stable since Node 23.6, available behind --experimental-strip-types since 22.6, Capacitor CLI already requires Node >=22). Projects on TypeScript <7 are unaffected; the existing transpileModule path is unchanged.

Fixes #8531

Tests or Reproductions

Verified against the minimal repro project linked in #8531 (bradenbiz/cap-ts7-repro), which pins typescript@7.0.2 and @capacitor/cli@8.3.3. npx cap config reproduces the exact failure from the issue before this fix, and correctly resolves the config (appId: 'com.example.repro', appName: 'repro', webDir: 'dist') after it.

Also verified in the same project:

  • Swapped in typescript@6 (the repro's own control case) and confirmed the pre-existing transpileModule path is untouched and still resolves the config correctly.
  • npm run build (tsc), npm run lint (eslint + prettier), and the full CLI Jest suite (npm test, 44 tests) all pass.

Screenshots / Media

N/A

Platforms Affected

  • Android
  • iOS
  • Web

Notes / Comments

await import() gets downleveled to a plain require() call by tsc when compiling to CommonJS (the CLI's build target), which silently defeats this fix since require() doesn't invoke Node's ESM loader/type-stripping. Worked around by constructing the import via new Function('specifier', 'return import(specifier)'), a standard idiom for preserving genuine dynamic import() semantics through a CJS-targeted tsc build. Flagging it explicitly here since it looks unusual on first read of the diff.

TypeScript 7 dropped the classic compiler API (transpileModule,
ModuleKind, etc.) from its default export, so requireTS's use of
ts.transpileModule throws on projects with typescript@7 installed and
every command that reads capacitor.config.ts fails immediately.

Detect when that API isn't available and fall back to Node's own
built-in TypeScript syntax stripping via a real dynamic import
(stable since Node 23.6, available behind --experimental-strip-types
since Node 22.6) instead of transpiling the file ourselves. Falls
back to a clear error if neither is available. Projects on older
TypeScript versions are unaffected: the existing transpileModule
path is unchanged.

Fixes ionic-team#8531
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 this pull request may close these issues.

[Bug]: capacitor.config.ts parsing fails with TypeScript 7 (Cannot read properties of undefined (reading 'CommonJS'))

1 participant