Skip to content

Prove the array indexing the types only asserted - #15

Merged
DelanoJoey merged 1 commit into
mainfrom
fix/strict-index-types
Sep 20, 2026
Merged

DelanoJoey merged 1 commit into
mainfrom
fix/strict-index-types

Conversation

@DelanoJoey

Copy link
Copy Markdown
Collaborator

Unblocks the gridiron integration. No behaviour change — and that claim is tested, not asserted.

What surfaced this

gridiron is the first consumer whose tsconfig sets noUncheckedIndexedAccess (marque and the rest don't), and because this package ships raw src/, the consumer typechecks our source. Eight errors appeared in concierge.tsx that no other site could see.

None are new. All are the same shape: an index read whose presence was asserted by a return type rather than proven.

before after
readCookie if (!match) narrows the match, not the group; catch then re-read match[1] check the group; catch returns the value it already had
parseRgba declared a 4-tuple, built from m[1..4] unchecked groups destructured and checked; a null match falls through the same branch
luminance destructured a .map() result as a 3-tuple — it's number[], so each channel was number | undefined one srgb() per channel, arity kept in the types

"Unchanged" is tested

Neither helper is exported, so the honest test is the observable one: does auto-theme still tell a dark page from a light one?

expect(onDark).not.toBe(onLight);

That assertion exists because the vacuous version is the trap — if parseRgba returned null for both, they'd land on the same fallback and a weaker test would pass. Mutations confirm it bites:

mutation result
parseRgba always null 1 fail
luminance always 1 1 fail
restored 10/10

jsdom implements no hit-testing, so elementFromPoint is stubbed — the auto path samples whatever sits under the bar.

Scope

concierge.tsx only — the entry gridiron imports. article-toc.tsx and bento-grid.tsx carry the same class of error and are left for whoever first consumes them strictly; fixing them here would be unverified churn in files this PR has no reason to touch.

Verification

  • suite 42/42 (2 new) · typecheck clean
  • concierge.tsx clean under --strict --noUncheckedIndexedAccess
  • version 1.4.0 → 1.4.1

Publishing is tag-triggered, so merging this does not release it.

🤖 Generated with Claude Code

gridiron is the first consumer whose tsconfig sets noUncheckedIndexedAccess,
and it typechecks this package's source because we ship raw src/. Eight
errors surfaced in concierge.tsx that no other site could see — none of them
new, all of them the same shape: an index read whose presence was asserted
by a return type rather than proven.

- readCookie destructured match[1] behind `if (!match)`, which narrows the
  match but not the group. The catch branch then reached for match[1] again,
  where `value` was already the same string.
- parseRgba declared a 4-tuple return and built it from m[1..4] unchecked.
  Now the groups are destructured and checked, and a null match falls through
  the same branch — identical behaviour, provable arity.
- luminance destructured a .map() result as a 3-tuple. A mapped array is
  number[], so each channel was number | undefined. Mapping each channel
  through one srgb() keeps the arity in the types.

Behaviour is unchanged, and "unchanged" is tested rather than asserted:
auto-theme now has a test that a dark page and a light page resolve to
DIFFERENT bar backgrounds. Forcing parseRgba to null fails it; forcing
luminance to 1 fails it. Without that pair the test would pass vacuously on
a shared fallback. (jsdom implements no hit-testing, so elementFromPoint is
stubbed.)

Scope is concierge.tsx only — the entry gridiron imports. article-toc.tsx
and bento-grid.tsx carry the same class of error and are left for whoever
first consumes them strictly.

Suite 42/42 · typecheck clean · concierge.tsx clean under
--strict --noUncheckedIndexedAccess.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@DelanoJoey
DelanoJoey merged commit 84f1c9d into main Sep 20, 2026
1 check passed
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