Skip to content

🏗️♻️:replace tsx with node's native typescript support - #1789

Merged
OpenINFbot merged 2 commits into
livefrom
chore/run-typescript-natively
Aug 10, 2026
Merged

🏗️♻️:replace tsx with node's native typescript support#1789
OpenINFbot merged 2 commits into
livefrom
chore/run-typescript-natively

Conversation

@DerekNonGeneric

@DerekNonGeneric DerekNonGeneric commented Aug 10, 2026

Copy link
Copy Markdown
Member

Node has stripped types without a flag since v22.18.0, and engines.node already pins 24.19.0, so the build tasks can run on node directly and tsx comes out of devDependencies.

Why this is smaller than it sounds

Nothing under build/ is actually TypeScript. All 34 .mts files are ESM JavaScript with JSDoc comments — no type annotations, and none of the syntax that needs code generation:

$ grep -rE "enum|namespace|declare|abstract|: (string|number|boolean)" build --include="*.mts"
(no matches)

So type stripping is a no-op here. The one thing tsx was really providing is resolution of TypeScript's .mjs.mts convention, which node deliberately does not do — the docs are explicit that the loader "does not need or use tsconfig.json". That bit in exactly two places, both of which named files that do not exist on disk:

was now
package.json exports (6 entries) ./build/utils.mjs ./build/utils.mts
build-images.mts from './imagize.mjs' from './imagize.mts'

Resolving @openinf/portal/… needed nothing at all: it is a package self-reference through exports, which node supports natively. Had it been tsconfig paths — which node ignores — this would not have been possible without another loader.

The second commit

Dropping tsx quietly forecloses enum, namespaces with runtime code, parameter properties, and import aliases. Node refuses them outright:

SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode

erasableSyntaxOnly surfaces the same thing as TS1294 while editing instead of when a task next runs. It adds no errors of its own — tsc --noEmit reports the same 146 pre-existing ones with and without it.

Note

Those 146 are unrelated and predate this PR (mostly TS2339 from PATHS being built up dynamically in build/shared/constants.mts). tsc is not run by any script — verify.ts uses biome — so this flag is advisory in the editor rather than enforced in CI. Node remains the real backstop, and its error names the problem clearly.

Verification

With tsx gone from devDependencies and no longer linked into node_modules/.bin:

  • nps build
  • nps test — all 13 verify tasks ✅
  • nps format.all ✅, leaving the tree unchanged
  • node server.mts boots Browsersync on :3000 serving _site/

No flags required anywhere; CI reads node-version-file: package.json, so it gets the pinned 24.19.0.

Note

To be precise about what this removes: tsx stays in the dependency tree regardless, because gulp-postcsspostcss-load-config takes it as an optional peer for loading TS-based postcss configs.

$ pnpm why tsx
tsx@4.23.9
└─┬ postcss-load-config@5.1.0
  └─┬ gulp-postcss@10.0.0
    └── @openinf/portal (devDependencies)

What goes away is our direct dependency on it and every use of it — nothing we run shells out to tsx, and it is no longer linked as a binary. Dropping the package entirely would mean replacing gulp-postcss, which is a separate question.

Note

The .mts extension is arguably wrong now — these are JavaScript files, and renaming all 34 to .mjs would remove even the type-stripping step. That is a much larger diff which would also move them from verify.ts/format.ts to the JS tasks, so I have left it alone; keeping .mts also leaves the door open to real TypeScript later.

List of any relevant issue numbers: none

@netlify

netlify Bot commented Aug 10, 2026

Copy link
Copy Markdown

Deploy Preview for gh-pages-openinf ready!

Name Link
🔨 Latest commit 198064b
🔍 Latest deploy log https://app.netlify.com/projects/gh-pages-openinf/deploys/6a79409c77d83c0008dbb426
😎 Deploy Preview https://deploy-preview-1789--gh-pages-openinf.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

DerekNonGeneric and others added 2 commits August 10, 2026 03:07
Node has stripped types without a flag since v22.18.0, and
engines.node already pins 24.19.0, so the build tasks can run on
`node` directly.

Nothing under build/ is actually TypeScript — 34 `.mts` files carrying
JSDoc, no annotations and no enum, namespace, parameter properties or
decorators — so stripping is a no-op here. The one thing tsx was
really providing is resolution of TypeScript's `.mjs` to `.mts`
convention, which node deliberately does not do: the package `exports`
named `./build/utils.mjs` and friends, and build-images reached for
`./imagize.mjs`, none of which exist on disk. Both now name the `.mts`
files they always meant.

Resolving `@openinf/portal/…` needed nothing special; it is a package
self-reference through `exports`, which node supports, rather than
tsconfig `paths`, which it ignores.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Now that the tasks run on node itself, `enum`, namespaces with runtime
code, parameter properties and import aliases stop being viable —
node rejects them outright with ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX.

erasableSyntaxOnly reports the same thing as TS1294 while editing,
rather than leaving it to be discovered when a task is next run. It
adds no errors of its own: `tsc --noEmit` reports the same 146
pre-existing ones either way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@DerekNonGeneric
DerekNonGeneric force-pushed the chore/run-typescript-natively branch from b2c69cb to 198064b Compare August 10, 2026 03:08
@OpenINFbot
OpenINFbot merged commit 872ef09 into live Aug 10, 2026
13 checks passed
@OpenINFbot
OpenINFbot deleted the chore/run-typescript-natively branch August 10, 2026 03:15
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.

2 participants