Skip to content

feat(cli): typescript init templates use tsc + tsx and swc/jest, on typescript 7#1719

Merged
mrgrain merged 3 commits into
mainfrom
iankhou-ts7-support
Jul 10, 2026
Merged

feat(cli): typescript init templates use tsc + tsx and swc/jest, on typescript 7#1719
mrgrain merged 3 commits into
mainfrom
iankhou-ts7-support

Conversation

@iankhou

@iankhou iankhou commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

TypeScript 7.0.2 was published on 2026-07-08. ts-node@10 reads the compiler's ts.sys API, which TypeScript 7 no longer exposes, and ts-node has no compatible release. ts-jest@29 likewise caps its peer dependency at typescript <7. Two consequences:

  1. Any generated CDK project whose owner manually upgrades typescript past ~5.9 crashes on cdk synth:
    TypeError: Cannot read properties of undefined (reading 'fileExists')
        at readConfig (.../ts-node/dist/configuration.js:91:33)
    
  2. The init-typescript-app integ test enumerates TypeScript versions live from npm, so 7.0 entered the matrix immediately and the integ_init-templates jobs fail on every PR.

This PR moves the TypeScript init templates to TypeScript 7 and replaces the compiler-API-dependent tooling:

  • App execution: npx tsc && npx tsx bin/<name>.tstsc type-checks (noEmit), then tsx (esbuild-based) runs the app. Follows @mrgrain's review suggestion, with plain npx chaining instead of npx -c for portability across npm versions and Windows.
  • Tests: jest with @swc/jest (transpile-only, no type checking). Faster than ts-jest, which we also can't use with TypeScript 7 due to ts-jest depending on ts-node. Type errors in test/ are still caught by npm run build, since the tsconfig includes the test directory.

Neither tsx nor swc drives the TypeScript compiler API, so the templates no longer break when the compiler's internals change.

Template changes

Made changes to typescript templates as follows:

For app + sample-app typescript variants

  • Upgrade typescript to v7
  • cdk.template.json: use app command npx tsc && npx tsx bin/<name>.ts
  • package.json: drop ts-node and ts-jest; add tsx, @swc/core, @swc/jest
  • tsconfig.json: add noEmit, isolatedModules (esbuild transpiles file-by-file), and an explicit types: ["jest", "node"] list — TS 6+ no longer auto-includes all of node_modules/@types
  • jest.config.js: transform @swc/jest
  • README: build/watch descriptions now say "type-check" since tsc no longer emits

For lib typescript variant

  • Similar to above changes, but omit noEmit, since there is no app command.

Test changes

  • The cli-integ version-matrix test installs tsx alongside the matrix's typescript version

Verified locally with a built CLI

  • Rendered all three templates into scratch projects with typescript@7.0.2: npm install resolves, npm run build passes under the Go-based compiler, npm test passes through @swc/jest, and the app command runs end to end
  • A deliberate type error fails npx tsc with exit 1, blocking synth
  • The template tsconfigs type-check under TS 5.5, 5.9, 6.0, and 7.0 (the integ test matrix spans versions younger than 2 years)

User-facing notes

  • Existing projects are not affected — this only changes what cdk init generates for new projects.
  • New projects start on TypeScript 7. tsc still type-checks every synth, but tsx (esbuild) executes the app, so synth and watch iterations are faster than ts-node's compiler-API path.
  • Jest no longer type-checks test files at test-time (swc is transpile-only); npm run build covers that.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
npm/@swc/core ^1.15.0 UnknownUnknown
npm/@swc/jest ^0.2.39 UnknownUnknown
npm/tsx ^4.23.0 UnknownUnknown
npm/typescript ~7.0.2 UnknownUnknown
npm/@swc/core ^1.15.0 UnknownUnknown
npm/@swc/jest ^0.2.39 UnknownUnknown
npm/typescript ~7.0.2 UnknownUnknown

Scanned Files

  • packages/aws-cdk/lib/init-templates/lib/typescript/package.json
  • packages/aws-cdk/lib/init-templates/sample-app/typescript/package.json

@aws-cdk-automation aws-cdk-automation requested a review from a team July 8, 2026 20:21
@iankhou iankhou force-pushed the iankhou-ts7-support branch from cee7dd8 to a6be7a1 Compare July 8, 2026 22:59
@iankhou iankhou force-pushed the iankhou-ts7-support branch from a6be7a1 to 392f284 Compare July 8, 2026 23:07
… ts-node

TypeScript 7.0.2 (the first stable release of the Go-based compiler) was
published on 2026-07-08. ts-node@10 reads the compiler's ts.sys API, which
TypeScript 7 no longer exposes, so the generated project's 'cdk synth'
crashes for anyone who upgrades — and the init-typescript-app integ test
matrix (enumerated live from npm) began failing on every PR the moment 7.0
appeared:

    TypeError: Cannot read properties of undefined (reading 'fileExists')
        at readConfig (.../ts-node/dist/configuration.js:91:33)

Rather than swapping in another third-party transpiler, drop the runner
entirely. The app command becomes:

    npx tsc && node bin/<name>.js

tsc exits non-zero on type errors, so 'cdk synth' still fails on type
errors exactly as it did with ts-node — with two template tweaks to keep
that property sound:

- noEmitOnError, so a failed compile can't leave stale JS behind that a
  subsequent synth would silently run
- an explicit types list (jest, node). TypeScript 6.0 changed the default
  of the 'types' option to [] (packages under node_modules/@types are no
  longer auto-included, per the TS 6.0 release notes). The template's test
  file uses jest globals, so a generated project whose owner upgrades to
  TS >= 6 fails to compile without this field — a latent break independent
  of ts-node (previously hidden at synth time because ts-node only
  compiled the bin/lib import graph; tsc compiles the whole project).
  Verified in isolation: same project compiles on 5.9, fails identically
  on 6.0 and 7.0 without the field, passes on all three with it. Note the
  version-matrix CI test itself never hits this (it deletes test/ before
  building); the field protects real users, not CI.

Test changes: the version-matrix test no longer installs any runner (just
the matrix's typescript version), and the devDependencies-stripping step
now also strips the tsconfig types list — with @types/jest removed, tsc
would otherwise error on the missing type package.

Verified end-to-end with a locally built CLI: init + synth under the pinned
typescript ~5.9, then again after upgrading the generated project to
typescript@7.0.2 — both clean; ts-node crashed on the latter. Full matrix
flow (strip devDependencies, install matrix version, build, run) verified
under 6.0 and 7.0; TypeScript 3.9 accepts the tsconfig option values.
@rix0rrr

rix0rrr commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Wait, isn’t the problem that ts-node doesn’t support TS7?

Then why are we/they pulling it in?

@@ -1,5 +1,5 @@
{
"app": "npx ts-node --prefer-ts-exts bin/%name%.ts",
"app": "npx tsc && node bin/%name%.js",

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.

I was thinking this:

Suggested change
"app": "npx tsc && node bin/%name%.js",
"app": "npx -c \"tsc && tsx bin/%name%.js\"",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Switched to tsc && tsx. Per our conversation, tsx is faster than ts-node anyway, and tsc is faster than it used to be, and now feasible here.

@iankhou

iankhou commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Wait, isn’t the problem that ts-node doesn’t support TS7?

Then why are we/they pulling it in?

It's automatically pulled in from NPM when we run our cli-integ test matrix, per the following logic:

export function typescriptVersionsYoungerThanDaysSync(days: number, versions: string[]): string[] {

Anything newer than 2 years old is pulled in.

iankhou added 2 commits July 9, 2026 14:59
…ypescript 7

TypeScript 7 drops the ts.sys API that ts-node and ts-jest rely on.
Replace both with tooling that doesn't depend on compiler internals:

- App execution: npx tsc (type-check only, noEmit) && npx tsx (esbuild)
- Tests: @swc/jest (transpile-only; npm run build still type-checks)
- Pin typescript to ~7.0.2 across all three TS templates (app, sample-app, lib)
- Add explicit types: ["jest", "node"] to lib/typescript tsconfig (required
  since TS 6+ no longer auto-includes all @types)
- Version-matrix integ test installs tsx alongside the matrix typescript version
@iankhou

iankhou commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Integ tests are passing on all tested version of typescript (released within 2 years).

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants