Repository navigation
Conversation
TypeScript 7 is the native compiler rewrite, and two things in this repo stop it dead: - `moduleResolution: "node"` (node10) was removed outright, so `tsc` refuses the project before it reads a single source file. The sources are bundled by rollup, so `"bundler"` is the mode that matches how they are consumed. - `ScrollBox` typed a timeout handle as `NodeJS.Timeout`. That only ever resolved because TypeScript 5.x silently includes every `@types` package it can find, and `@types/node` is a devDependency here. TypeScript 7 does not, so it fails - and because the member is `protected`, the name is emitted into `lib/ScrollBox.d.ts`, which means the published declarations have been asking consumers for `@types/node` all along. `ReturnType<typeof setTimeout>` says the same thing without reaching for a Node global. To keep it working, TypeScript 7 is installed alongside 5.x rather than replacing it: eslint, ts-jest and storybook all reach for the compiler's JS API, which 7.x no longer ships, so a straight bump breaks the toolchain. The alias keeps `node_modules/.bin/tsc` pointing at 5.x - `xs lint`, `xs types` and `xs build` are untouched - and the new scripts invoke 7.x by path. - `npm run types` now checks the sources with both compilers. - `npm run types:dist` checks the emitted `lib/*.d.ts` with 7.x, through the entry point consumers import, with no ambient `@types` and `skipLibCheck` off. That last part is what would have caught the `NodeJS.Timeout` leak: a bad type on a `protected` member only ever surfaces as a diagnostic inside a `.d.ts` file. It also drags pixi.js's own declarations into the check, and those are not clean on 7.x - pixi.js references `@webgpu/types`, which now collides with the WebGPU types built into `lib.dom.d.ts` - so diagnostics from outside this repo are counted and reported but not treated as failures. Co-Authored-By: Claude Opus 5 <[email protected]>
CyberDex
marked this pull request as draft
September 30, 2026 15:42
The `@webgpu/types` collision was described as an open pixi.js problem. It is not: pixi.js v8.21.0 dropped the `@webgpu/types` reference from its non-legacy declarations, and a consumer on it compiles clean under TypeScript 7 with `skipLibCheck` off. The hundreds of diagnostics this repo sees come from the pixi.js it pins for development - 8.6.2, sixteen minors behind what `^8.6.2` resolves to for anyone installing today. Measured against the published `@pixi/[email protected]` with `skipLibCheck` off: pixi.js 8.6.2 TypeScript 7 185 errors pixi.js 8.20.1 TypeScript 7 183 errors pixi.js 8.21.0 TypeScript 7 1 error pixi.js 8.22.0 TypeScript 7 1 error That last error is ours - the `NodeJS.Timeout` leak this branch fixes. So on current pixi.js it is the only thing standing between a consumer and a clean TypeScript 7 build, rather than one problem among many. Updating the pinned pixi.js is left alone deliberately: it is a migration of its own, not a TypeScript 7 change. 8.22.0 tightens `Container.parent` and `maxWidth` to nullable, which is six new strict-null errors in `List`, `Slider`, `SliderBase` and `DoubleSlider`, and it also breaks the jest transform. Co-Authored-By: Claude Opus 5 <[email protected]>
… not Merging main makes half this branch redundant and the other half more worthwhile. #285 already changed `ScrollBox`'s timeout handle to `ReturnType<typeof setTimeout>`, identically, so that part merged away and `@pixi/[email protected]` ships clean of the Node global. What main still has is `moduleResolution: "node"`, which TypeScript 7 removed, so the project does not compile under it at all. That, and the checks, are what is left here. The declaration check reads better against main than it did against 2.3.2: #286 added seventeen per-component subpath exports, each promising its own `types` target, and nothing verifies those point at files that were actually built. A subpath with a typo in `types` does not fail a build - the import quietly resolves to `any` in the consumer's project. So check.mjs now walks the `exports` map and fails on any entry whose declaration is missing, while consumer.ts keeps covering declaration *content* through the root entry, which re-exports every module. Also updates consumer.ts for `Drawer`, `Signal` and the `input` subpath, and adds a `paths` wildcard mirroring how `exports` resolves subpaths. Unrelated, but main's lint is red and takes this PR's CI with it: `scripts/build-umd.mjs` from #286 reports to stdout, and `xs lint` runs with `--max-warnings 0`. Silenced with the same disable comment used elsewhere in the repo. Worth landing on main directly - `testing.yml` only runs on pull_request, so nothing catches this after a merge. Co-Authored-By: Claude Opus 5 <[email protected]>
CyberDex
marked this pull request as ready for review
October 2, 2026 09:32
`types:dist` only guarded pull requests, so the hole it exists to close was still open where it matters: `npm run release` goes straight from `build` to `publish`. A bad declaration reaching npm is exactly how `NodeJS.Timeout` shipped and had to be fixed after the fact in #285. The build output is already there by that point, so it costs a fraction of a second and `release` stops before `publish` rather than after. Co-Authored-By: Claude Opus 5 <[email protected]>
CatchABus
approved these changes
Oct 2, 2026
CatchABus
left a comment
Collaborator
There was a problem hiding this comment.
We can proceed with this but I'd treat it as a workaround solution until TS 7 is mature enough and the mentioned packages finally support it.
This branch has not been deployed
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.
What
Makes the project compile under TypeScript 7, the native compiler rewrite, and adds the checks that keep the published declarations usable there.
The blocker
TypeScript 7 removed
moduleResolution: "node"(node10), and main still sets it. The compiler refuses the project before reading a single source file:The sources are bundled by rollup, so
"bundler"is the mode that matches how they're consumed, and it needs no changes to import specifiers (unlikenode16/nodenext). With that one line changed, main's sources —Drawer, theinputpackage,Signaland all — type-check clean on 7.0.2.Why TypeScript 7 is installed alongside 5.x, not instead of it
typescript@7ships a native binary and a thin wrapper — the classic JS compiler API is gone (its only main export islib/version.cjs). eslint, ts-jest and storybook'sfork-ts-checkerall reach for that API, so a straight bump takes the toolchain down. Confirmed by trying it:So 7.x goes in under an alias:
node_modules/.bin/tsckeeps resolving to 5.x (verified deterministic across install orders andnpm ci), soxs lint,xs typesandxs buildare untouched. The new scripts invoke 7.x by path. Nothing new is published — the alias is a devDependency, and the platform binaries areoptionalentries in the lockfile, so each CI runner only downloads its own.What's checked now
npm run types— sources, through both compilers.npm run types:dist(new CI step, afterbuild) — the built declarations, two ways.Content.
consumer.tsimports the root entry withskipLibCheckoff and no ambient@types. That's what gives the check teeth: a bad type on aprotectedmember only ever surfaces as a diagnostic inside a.d.tsfile, soskipLibCheck: truehides it completely — which is exactly how theNodeJS.Timeoutleak reached npm and had to be fixed reactively in #285. Since the root entry re-exports every module, naming it pulls the whole declaration output into the program.Wiring. #286 added seventeen per-component subpath exports, each promising its own
typestarget, and nothing verifies those point at files that were built. A typo in a subpath'stypesdoesn't fail a build — the import quietly resolves toanyin the consumer's project.check.mjsnow walks theexportsmap and fails on any entry whose declaration is missing.npm run releaseruns the check betweenbuildandpublish, so this guards the path the bug actually escaped through, not just pull requests.Both failure modes verified:
NodeJS.Timeoutreintroduced intolib/ScrollBox.d.tsexportsentry pointing at a missing declarationBecause
skipLibCheckis off, dependency declarations get checked too — 181 diagnostics against the pinned pixi.js 8.6.2, which this repo can't fix.check.mjscounts and reports them but only fails on diagnostics from files inside the repo, so an upstream regression can't block a release here.Unrelated one-liner, but it's blocking CI
Main's lint is currently red, and it takes every PR with it:
scripts/build-umd.mjsfrom #286 reports to stdout, andxs lintruns--max-warnings 0.Silenced here with the same disable comment used elsewhere in the repo, only so this PR can be verified — probably worth landing on main directly. Worth noting
testing.ymlonly runson: [pull_request], so nothing catches this after a merge.On pixi.js and TypeScript 7
Measured by installing published
@pixi/uinext to pixi.js and compiling a consumer withskipLibCheckoff:pixi.js
v8.21.0dropped the@webgpu/typesreference that collided with the WebGPU types now built into TypeScript 7'slib.dom.d.ts. So pixi.js is not a blocker for TypeScript 7 consumers — but this repo develops against 8.6.2, sixteen minors behind. Updating that pin is a migration of its own (8.22.0 tightensContainer.parentandmaxWidthto nullable — six new strict-null errors — and breaks the jest transform), so it's deliberately left for a separate PR.Verification
Full CI sequence on the merged branch, clean install:
npm run lintnpm run types(5.x + 7.x)npm run testnpm run docsnpm run buildnpm run types:distexportsentries🤖 Generated with Claude Code