Skip to content

chore(deps): bump typescript-eslint 8.19.0 → 8.66.0 (#86 sweep, step 1) - #171

Merged
tyler-rich merged 1 commit into
devfrom
claude/typescript-eslint-8-19-0-bf7axh
Aug 9, 2026
Merged

chore(deps): bump typescript-eslint 8.19.0 → 8.66.0 (#86 sweep, step 1)#171
tyler-rich merged 1 commit into
devfrom
claude/typescript-eslint-8-19-0-bf7axh

Conversation

@tyler-rich

@tyler-rich tyler-rich commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Step 1 of the eight-step sequence in docs/upgrades/frontend-toolchain-86.md, taken alone because it is the only unblocking move in the set. The pinned 8.19.0 capped typescript at <5.8.0 and eslint at ^9; 8.66.0 raises those to <6.1.0 and ^10.0.0, which is what steps 2 (ESLint 10) and 4 (TypeScript 6.0.3) are gated behind.

Scope held exactly: only typescript-eslint moves. No ESLint or TypeScript config was edited, typescript stays at 5.7.2 and eslint at 9.39.4, no later sweep step is touched, and #153 remains open and unactioned.

Target re-checked against the registry rather than taken from the document: latest is still 8.66.0, with only 8.66.1-alpha.* canaries beyond it. The §3.1 one-liner also still returns typescript: >=4.8.4 <6.1.0, so the TypeScript 6.0.3 ceiling holds as of today.


⚠️ Two of the scoping document's predictions did not hold

Both are recorded in docs/ARCHIVE.md §14, and both matter for the remaining steps.

1. An existing rule's implementation got stricter

The prediction that the rule set is unchanged is correct and was confirmed at the artifact: 8.19.0's dist/configs/recommended-type-checked.js and 8.66.0's dist/configs/flat/recommended-type-checked.js are identical — 50 entries either side, 43 @typescript-eslint/* rules plus 7 core disables, same severities, same options.

But an unchanged rule set does not imply an unchanged set of reports. Across 47 minors @typescript-eslint/no-unnecessary-type-assertion learned to catch a case it previously missed, and fired twice on code that has been in the tree unchanged:

Rule Count Sites
@typescript-eslint/no-unnecessary-type-assertion 2 NewScanPage.tsx:139 registryId: '' as string
NewScanPage.tsx:140 gitCredentialId: '' as string

Both assertions were genuinely redundant ('' already widens to string as a mutable object-literal property) and both were removed by hand at those two sites only — no --fix, no bulk autofix. tsc -b passes afterwards, confirming useForm's inferred initialValues type is unchanged, and the emitted bundle keeps the same content hashes (index-BNB6IweX.js, index-D2wHtcHV.css), which is the proof a type-only assertion erases to identical JavaScript.

The transferable rule: "no new rules" does not mean "no new findings." §0.3's headline — "The typescript-eslint bump does not change which rules run" — reads as a reassurance about outcomes and gets cited as one. Step 1's own row is more careful ("only detection improves", priced S–M / 1–3 h "dominated by however many reports appear"), so the budget was right; the headline is what misleads. Steps 2 and 4 both cross far more implementation change than config change.

2. The effective rule set did change — the claim is wrong, not just incomplete

§0.3 states the shipped recommendedTypeChecked is "byte-for-byte identical… nothing added, removed, or re-severitied." The cause of the error is scope: tseslint.configs.recommendedTypeChecked is a three-layer composite (base + eslint-recommended + recommended-type-checked), and the document diffed only the third file, then generalised to the whole composite.

File 8.19.0 8.66.0 Verdict
dist/configs/…/recommended-type-checked.js (diffed by the doc) 50 entries 50 entries identical
dist/configs/eslint-recommended-raw.js (not diffed by the doc) 22 entries 23 entries + no-with: 'off'

Because eslint.config.js extends js.configs.recommended before the tseslint layers, eslint --print-config shows no-with going from error ([2]) to off ([0]) across all three file classes — app .tsx, library .ts, and the test override. The only other resolved-config difference is the parser identity string, which is expected.

Accepted rather than restored, with the premise verified rather than argued. The "with is already a compile error" case only holds under strict mode, and a non-module .ts file is not strict by default. Both tsconfigs set "strict": true and "moduleDetection": "force" — and rather than stop at the flags, a probe file containing a with statement was compiled: tsc -b returns TS1101: 'with' statements are not allowed in strict mode plus TS2410. Probe deleted. no-with was not re-added to eslint.config.js; one line in the rules block restores it if that judgement is revisited.

Standing consequence for the rest of the sweep

The document's evidence discipline is genuinely good — every claim cited to a published peer range or an upstream guide, eleven tarballs unpacked to check artifacts directly. The failure here was not sloppiness but scope: one file diffed, conclusion stated about a composite of three. Steps 2, 3 and 4 rest on comparable single-artifact reads (the 14 React Compiler rules from eslint-plugin-react-hooks@7.1.1's bundle, the three new eslint:recommended rules from @eslint/js@10.0.1, the TypeScript 6.0 option audit). Each should be re-verified against the installed tree when its step runs, not trusted.


Lockfile — everything that moved

package.json changed one line. The lockfile went 374 → 362 packages; every movement is inside the typescript-eslint subtree or orphaned by it, attributed by parsing both lockfiles and resolving each removed package's requirers.

  • 12 version bumps — the ten @typescript-eslint/* packages 8.19.0 → 8.66.0, plus ts-api-utils 1.4.3 → 2.5.0 and, nested under typescript-estree, minimatch 9.0.9 → 10.2.6 and brace-expansion 2.1.4 → 5.0.9.
  • 5 added@typescript-eslint/project-service and @typescript-eslint/tsconfig-utils (new first-party splits of typescript-estree), plus three nested copies that exist only because the top-level ones stay pinned for ESLint 9: ignore@7.0.6, eslint-visitor-keys@5.0.1, balanced-match@4.0.4.
  • 17 removedtypescript-estree swapped fast-glob for tinyglobby, which was already in the tree at 0.2.17 and satisfies its ^0.2.15, so nothing new landed. Dropping fast-glob orphaned its whole subtree: @nodelib/fs.{walk,scandir,stat}, fastqreusify, run-parallelqueue-microtask, merge2, micromatchbracesfill-rangeto-regex-rangeis-number, the top-level picomatch@2.3.2, and the nested fast-glob/node_modules/glob-parent@5.1.2. graphemer went with the eslint-plugin. Each was checked to have no surviving requirereslint's own top-level glob-parent@6.0.2 and vite/vitest's nested picomatch@4.x are untouched.

lockfileVersion stays 3 with no normalization churn, because the lockfile was written with npm 11.19.0 in a scratch prefix to match CI's Node 24 rather than the sandbox's npm 10.9.7 — the method recorded in the 2026-08-09 lockfile-refresh entry. Worth repeating: a 486-line diff from a real dependency change is hard to audit with a whole-file re-normalization mixed in.

Verification

The pre-bump baseline was re-measured on 8.19.0 rather than quoted, and reproduced the document's §1 exactly. After the bump and the two-line fix, from a fresh rm -rf node_modules && npm ci:

Baseline (8.19.0) After (8.66.0)
npm run lint clean clean
npm run format:check clean clean
npm test 21 files / 79 tests 21 files / 79 tests
npm run build 7035 modules, 645.18 kB JS / 201.38 kB CSS identical, same asset hashes
npm audit 0 0

package-lock.json's SHA is stable across npm ci.

See docs/ARCHIVE.md § Deviations for the full record of what changed in this step.

Step 1 of the eight-step frontend toolchain sweep in
docs/upgrades/frontend-toolchain-86.md, taken alone because it is the only
unblocking move in that sequence. The pinned 8.19.0 capped typescript at
<5.8.0 and eslint at ^9; 8.66.0 raises those to <6.1.0 and ^10.0.0, which
is what steps 2 (ESLint 10) and 4 (TypeScript 6.0.3) are gated behind.

Only typescript-eslint moves. No ESLint or TypeScript config was edited,
typescript stays at 5.7.2 and eslint at 9.39.4, and no later sweep step is
touched.

Two of the scoping document's predictions did not hold:

- An existing rule's implementation got stricter. The rule set is unchanged
  as predicted (recommended-type-checked.js is identical across the span,
  50 entries either side), but no-unnecessary-type-assertion now catches
  what it previously missed and reported two redundant `'' as string`
  assertions in NewScanPage.tsx. Removed by hand at those two sites only;
  tsc -b confirms the inferred useForm type is unchanged and the emitted
  bundle keeps the same content hashes. "No new rules" does not mean "no
  new findings."
- The effective rule set did change. The document's byte-for-byte claim
  diffed one of the three files recommendedTypeChecked composes; the layer
  it did not diff gains `no-with: 'off'`, dropping that rule from error to
  off in the resolved config. Accepted rather than restored: `with` is a
  hard compile error under this repo's tsconfigs, verified at the compiler
  (TS1101 plus TS2410) rather than argued from the strict flag.

Lockfile movement is confined to the typescript-eslint subtree, 374 -> 362
packages, with each of the 17 removals checked to have no surviving
requirer. Written with npm 11.19.0 to match CI's Node 24.

Suites unchanged against a re-measured pre-bump baseline: lint clean,
Prettier clean, 79 tests across 21 files, 7035 modules to 645.18 kB JS /
201.38 kB CSS, npm audit 0 at every severity.

See docs/ARCHIVE.md section 14 for the full record.
@tyler-rich
tyler-rich merged commit a99815a into dev Aug 9, 2026
8 checks passed
@tyler-rich
tyler-rich deleted the claude/typescript-eslint-8-19-0-bf7axh branch August 9, 2026 10:45
tyler-rich added a commit that referenced this pull request Aug 9, 2026
…r 8 (#189)

Three Track A edits in docs/ROADMAP.md, each gated on a live check made
this session rather than on a prior session's claim:

- Strike the "Frontend tooling majors from Dependabot #86" item as Done
  2026-08-09, naming all eight sweep PRs (#171, #174, #177, #179, #180,
  #183, #185, #187) and both deliberately-excluded packages (TypeScript 7
  and @types/node 26). All eight squash commits re-confirmed present on
  dev before writing the bullet.

- Strike the GHSA-qwww-vcr4-c8h2 re-cut request: the advisory has already
  been re-cut upstream to >= 7.12.0, < 7.18.2 plus >= 8.0.0, < 8.3.0,
  with the 8.x range untouched. Verified against the record in
  github/advisory-database and independently against the npm registry's
  advisory endpoint, which returns nothing for 7.18.2.

- Reword react-router 7 -> 8 as blocked on a React 19 decision rather
  than on a tooling bump, and move it out of the tooling-majors grouping
  into Longer-term / speculative. react-router@8.3.0 peers react and
  react-dom at >=19.2.7; this repo pins both at 18.3.1.

See docs/ARCHIVE.md section 14 for the dated record of what was verified
for each.
tyler-rich added a commit that referenced this pull request Aug 9, 2026
…a current reason (#193)

Comment-only change to the npm /frontend entry. No ignore rule, group,
schedule, target-branch or any other key is added, removed or modified.

The paragraph's instruction — leave the frontend tooling majors unignored
so Dependabot keeps surfacing them — is still correct. Its stated reason
was not: it called them "the deferred #86 sweep" and said to surface them
"until that PR is done". The sweep completed 2026-08-09 across #171,
#174, #177, #179, #180, #183, #185 and #187, and docs/ROADMAP.md marks
the item Done (verified before writing). So the comment had begun
arguing against its own instruction — a reader who checked the roadmap
would find the work finished and reasonably conclude the exemption had
expired, whose obvious next move is to add the typescript ignore, which
is the one thing that must not happen.

Rewritten so the instruction rests on two current reasons. The tooling
majors stay unignored as ordinary policy: we want to see them, evaluate
them and land them, which is exactly what the sweep did (pointing at
docs/upgrades/frontend-toolchain-86.md rather than restating it).
typescript stays unignored for a sharper reason: TypeScript 7 is wanted,
the blocker is entirely upstream, and the regenerating Dependabot PR
proposing 7.x IS the notification that tells us when typescript-eslint
ships support — an ignore would suppress the signal while changing
nothing about the blocker. The re-check command is inlined so the next
reader can test it without a session, along with the expected shape of
support (a new typescript-eslint MAJOR built against TS 7's ./unstable/*
API, not a point-release range widen).

Verified by parsing rather than by reading: both versions load with
yaml.safe_load to byte-identical canonical JSON (SHA-256 07e71c6c on each
side), and every changed raw line matches ^[+-]\s*#.
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.

1 participant