test(react): type-check the whole test tree, and retire the narrow typetests project (#4040) - #4351
Merged
Merged
Conversation
…petests project (#4040) `@object-ui/react` gains a `tsconfig.test.json` chained from `type-check`, so its 36 test files are compiled by something for the first time. Measured at the branch point: 46 raw errors, 43 code-tier once the config-tier noise is gone — against a TEST_DEBT entry that declared 27. All 43 are fixed in the tests. Two mock-typing families account for 20 of them (`ReturnType<typeof vi.spyOn>` / zero-arity `vi.fn` degrade `mock.calls` to the empty tuple, so several `calls[0][0]` assertions were reading `undefined` as far as the compiler was concerned), 11 are `React.createElement(C, props, children)` against a component whose props require `children`, and 11 are one fixture that had to be annotated so its three deliberately-retired keys could be marked `@ts-expect-error` instead of hiding among accidents. The substantive one is `SpecBridge.test.ts`: its ListView fixtures were authored in a dialect `@objectstack/spec` does not have — `rowHeight: 'comfortable'`, a `{ href }` object for the boolean `link`, `sort: { field, direction }`, `filter` as a field→value map, `grouping: { field }`. The bridge forwards those keys verbatim, so every assertion passed by round-tripping input that no spec-valid list view can carry. Re-spelled canonically; the density case now covers all five values `RowHeightSchema` admits. Per #4291's ratchet, `tsconfig.typetests.json` is retired in the same PR: the full project compiles the file it named (1 of 630, by `--listFiles`) and a provably-false `Assert` appended to that file turns the full project red. Refs #4040, #4291, #3181, #3009. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 11, 2026 21:12
yinlianghui
pushed a commit
that referenced
this pull request
Aug 11, 2026
… components removal is this PR's; retired-list union
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.
Part of #4040 (tranche 4, package 1 of 2). Sibling: #4355 (
components). Refs #4291, #3181, #3009.@object-ui/reactnow type-checks its whole test tree: atsconfig.test.jsonper the tranche template, chained from
type-check, plus the 43 code-tiererrors that were hiding behind the exclusion. Its
TEST_DEBTentry is deletedand — per #4291's new ratchet — its narrow
tsconfig.typetests.jsonis retiredin the same PR.
Remeasurement first: the registry said 27, the package has 43
Tranche 3's ruling is that the
TEST_DEBTnumbers are not to be trusted(i18n declared 13 and measured 103). Measured here at the branch point, writing
every compiler run to a FILE and counting from the file — never piping a
compiler through
head, which is how SIGPIPE produced a plausible false countonce already:
paths: {},composite: false, …)Declared: 27. Measured: 43 (1.6x). Dominant codes: TS2322 x18, TS2769 x11,
TS7006 x4, TS2493 x3.
The 43, by family
1. Mock typings that erased their own assertions (20).
let warnSpy: ReturnType< typeof vi.spyOn >resolves to the un-instantiatedMockInstance< Procedure | Constructable >, whosemock.callsdegrades to animplicitly-
anyelement type; a zero-arityvi.fn()typesmock.calls[0]asthe EMPTY tuple. So
const [term, opts] = ds.searchAll.mock.calls[0]inuseRecordSearch.test.tswas destructuringundefinedas far as the compilerwas concerned, in the case whose entire point is that
opts.objectscarries thefull whitelist. Fixed by naming the real signature —
MockInstance< typeof console.warn >, and declared (unused,_-prefixed) parameters on the searchmocks.
2.
createElement(C, props, children)wherechildrenis required (11).The third-argument form does not satisfy
Attributes & PwhenPrequireschildren; the eleven wrappers now passchildrenin the props object. Nobehaviour change —
createElement's third argument overwritesprops.childrenanyway.
3. One fixture with three deliberately-retired keys (11 call-site errors).
sampleActionsinuseActionEngine.test.tsdeclaresbulkEnabled,shortcutand
locations: ['global_nav']— all three retired in@objectstack/spec17.0.0-rc.6, and all three kept ON PURPOSE, because the tests around them are
INVERSE tests (
does not harvest the retired bulkEnabled key,does not offer an action declaring the retired global_nav location). Deleting them would deletethe only input that can prove the retirement holds. The array is now annotated
ActionDef[]and each stale key carries@ts-expect-errorwith the reason —which makes the retirement compiler-enforced in both directions: re-admit any of
these keys to the spec and the now-unused directive reports TS2578.
4. A fixture using a tombstoned theme key (1).
ThemeProvider.test.tsxauthored
typography.fontSize, retired to a tombstone in@objectstack/spec 17.0.0-rc.3 (objectstack#5021) with
theme.customVarsas theprescription. Nothing in the file asserted on it.
5.
SpecBridge.test.ts— a whole suite authored in a dialect the spec doesnot have (8). This is the one worth reading:
@objectstack/specdeclaresrowHeight: 'comfortable'/'spacious'/'small'short | compact | medium | tall | extra_talllink: { href: '/status' }link?: booleanaction: { type: 'navigate' }action?: stringsort: { field, direction }sort?: string | { field, order }[]filter: { status: 'active' }filter?: { field, operator, value }[]grouping: { field: 'region' }grouping?: { fields: [...] }bridgeListViewforwards every one of those keys verbatim (if (spec.sort) node.sort = spec.sort), so each assertion passed by round-tripping its owninput — proving pass-through and nothing about the contract. Re-spelled
canonically. The density case now covers all five values
RowHeightSchemaadmits (and gains
mediumandtall, which it never had).That leaves
mapDensity's branches forcomfortable/spacious/small/largeunreachable from any spec-valid input. Filed as #4352 rather thandeleted here — removing a lenient fallback is a behaviour change for hosts still
passing the legacy spellings, and this PR's scope is the type-check graduation.
Retiring the narrow project (#4291's ratchet)
testsCoveredis now true for this package, so keepingtsconfig.typetests.jsonis an error by the rule #4291 added. Retired here,with the same two-part proof:
Coverage —
tsc -p tsconfig.test.json --listFileswritten to a file andgrepped (never piped through
head):Discrimination — a provably-false assertion in the file's own vocabulary
appended to that file, the FULL project run, then reverted:
Coverage moved, it did not vanish.
The surviving environment is equal or wider. Both projects
extendstheroot
tsconfig.jsonand neither overrides any strictness flag, sostrictandfriends are identical by construction. The differences all go one way:
libgains
DOM.Iterable(["ES2020","DOM"]to["ES2020","DOM","DOM.Iterable"]),typesgains@testing-library/jest-domon top of["node"],jsxandpaths: {}match exactly. A widerlibcannot make a failing spec-parityassertion pass; it only adds globals the file never references.
Verification
node scripts/check-type-check-coverage.mjs— green:36/40 packages compile their tests, 4 declared debt (162 errors outstanding), 3 with a narrow type-assertion project(was 35/40, 5 debt, 4 narrow).
Type Check— green on this branch.was piped through
head.Changeset: empty frontmatter. Only test files, checking-only tsconfig projects,
one
type-checkscript and the coverage registry move; nothing publishedchanges.
Registry race
This PR and #4355 each delete one line from
TEST_DEBTinscripts/check-type-check-coverage.mjsand each append one name to theretired-narrow-project list in the gate's own suite. Whichever lands second will
conflict there; GitHub silently disables auto-merge on conflict, so it will need
re-arming after the resolve (merge
origin/main, take main's registry minus thispackage's line, re-run the coverage script, commit).
Generated by Claude Code