Skip to content

Add JSDoc type checking with a grow-only strict ratchet - #10

Open
turegjorup wants to merge 3 commits into
feature/eslint-frontend-lintingfrom
feature/typecheck-ratchet
Open

Add JSDoc type checking with a grow-only strict ratchet#10
turegjorup wants to merge 3 commits into
feature/eslint-frontend-lintingfrom
feature/typecheck-ratchet

Conversation

@turegjorup

Copy link
Copy Markdown

Adds a TypeScript checkJs gate over the JS frontend, scoped by a grow-only path list.

Stacked on feature/eslint-frontend-linting — review that one first; this PR targets it, not
release/3.0.0.

Changes

  • tsconfig.checkjs.jsoncheckJs with noImplicitAny off by default
  • scripts/typecheck-strict.mjs — filters diagnostics to the paths in .typecheck-strict-paths
  • .typecheck-strict-paths — the plain-text ratchet list
  • Adds the task and CI workflow, documented in the README

Why

Syntactic linting cannot catch a wrong property name; a typo in valid JS is invisible to it.
Type checking catches it, but only where the shape is annotated, and a JSDoc-presence rule would
accept @param {object} and catch nothing. So the gate is semantic: noImplicitAny makes every
read or write through an unannotated shape an error, forcing the annotation that tsc verifies.

tsc checks the whole import graph, so a files list cannot isolate a file — hence filtering
diagnostics by path instead. The list is plain text so the ratchet shows up in review, and it only
grows: add every assets/ file you touch and burn its findings to zero.

Syntactic linting cannot catch a wrong property name — the 523 root
cause was a .slide/.slides typo in valid JS. Type checking can, but only
where the shape is annotated, and a JSDoc-presence rule would accept
@PARAM {object} and catch nothing. So the gate is semantic:
noImplicitAny makes every read or write through an unannotated shape an
error, which forces the annotation that tsc then verifies.

tsc checks the whole import graph, so a files list cannot isolate a file;
scripts/typecheck-strict.mjs filters diagnostics to the paths listed in
.typecheck-strict-paths instead. The list is plain text so the ratchet
shows up in review, and it only grows: add every assets/ file you touch
to it in the same PR and burn its findings to zero.
The parameter was annotated {object}, which the typeof narrowing on the
next line reduces to never — so the annotation described something the
function cannot accept. It takes an unknown value.
@turegjorup

Copy link
Copy Markdown
Author

Follow-up notes — fallout from this PR

File these as issues, then replace the @TODO markers in the code with the issue numbers.

  1. Normalise the five logger.log(...) calls to logger.info(...) — type-level only. pino
    has no .log in its types but does have it at browser runtime (verified on pino 9), so these
    are not runtime bugs.

  2. TS 7 adoption — blocked on @eslint-react supporting the native compiler API.
    typescript@7.0.2 (the Go native port) was verified byte-identical to 5.9 in type-check output
    on this codebase (two full diffs, zero differing lines), but it does not expose the JS compiler
    API, which crashes @eslint-react. Diagnostics were proven identical, so it is a
    performance-only upgrade when unblocked — nothing is lost by waiting.

  3. The schedule-service fix PR must add assets/client/service/schedule-service.js to
    .typecheck-strict-paths
    , carrying RegionEntry / RegionPlaylist / RegionSlide
    typedefs. Verified: with the file on the list and unannotated, the gate fails with TS7053 at
    the this.regions[regionId] sites; with the typedefs in place the historical .slide/.slides
    typo fails as TS2551. That annotation is the bug's regression guard — the typo was already
    reintroduced once.

Items 1–6 and 8 concern the ESLint gate and are on that PR instead.

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