🏗️♻️:replace tsx with node's native typescript support - #1789
Merged
Conversation
✅ Deploy Preview for gh-pages-openinf ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
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
force-pushed
the
chore/run-typescript-natively
branch
from
August 10, 2026 03:08
b2c69cb to
198064b
Compare
OpenINFbot
approved these changes
Aug 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Node has stripped types without a flag since v22.18.0, and
engines.nodealready pins24.19.0, so the build tasks can run onnodedirectly andtsxcomes out ofdevDependencies.Why this is smaller than it sounds
Nothing under
build/is actually TypeScript. All 34.mtsfiles are ESM JavaScript with JSDoc comments — no type annotations, and none of the syntax that needs code generation:So type stripping is a no-op here. The one thing
tsxwas really providing is resolution of TypeScript's.mjs→.mtsconvention, which node deliberately does not do — the docs are explicit that the loader "does not need or usetsconfig.json". That bit in exactly two places, both of which named files that do not exist on disk:package.jsonexports(6 entries)./build/utils.mjs./build/utils.mtsbuild-images.mtsfrom './imagize.mjs'from './imagize.mts'Resolving
@openinf/portal/…needed nothing at all: it is a package self-reference throughexports, which node supports natively. Had it been tsconfigpaths— which node ignores — this would not have been possible without another loader.The second commit
Dropping
tsxquietly foreclosesenum, namespaces with runtime code, parameter properties, and import aliases. Node refuses them outright:erasableSyntaxOnlysurfaces the same thing asTS1294while editing instead of when a task next runs. It adds no errors of its own —tsc --noEmitreports the same 146 pre-existing ones with and without it.Note
Those 146 are unrelated and predate this PR (mostly
TS2339fromPATHSbeing built up dynamically inbuild/shared/constants.mts).tscis not run by any script —verify.tsuses 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
tsxgone fromdevDependenciesand no longer linked intonode_modules/.bin:nps build✅nps test— all 13 verify tasks ✅nps format.all✅, leaving the tree unchangednode server.mtsboots Browsersync on:3000serving_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:
tsxstays in the dependency tree regardless, becausegulp-postcss→postcss-load-configtakes it as an optional peer for loading TS-based postcss configs.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 replacinggulp-postcss, which is a separate question.Note
The
.mtsextension is arguably wrong now — these are JavaScript files, and renaming all 34 to.mjswould remove even the type-stripping step. That is a much larger diff which would also move them fromverify.ts/format.tsto the JS tasks, so I have left it alone; keeping.mtsalso leaves the door open to real TypeScript later.List of any relevant issue numbers: none