Type src/ against API and database shapes, fixing implicit anys

Adds .d.ts declarations beside the untyped JS modules imported from
TS (api.js, navConfig.js, adminSchema.js, adminNav.js, src/data/*),
with shapes taken from the server routes and migrations. get/post/
patch/del now return unknown unless the caller names the response.

Fixes found along the way:
- website/email/instagram are bare strings from splitLinks, not Link
  objects; OrganizationDetail's website and email pills rendered with
  no href or label and now link correctly.
- The chapter map falls back to FALLBACK_COLOR for a region with no
  colour instead of painting its tiles black.

Adds defineSection() so each page manifest entry's props are checked
against its own Component.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Zaldimmar 2026-09-25 04:13:46 -05:00
parent 5286cae9ca
commit 2428f4412a
39 changed files with 1318 additions and 343 deletions

View file

@ -164,7 +164,7 @@ export default function PeopleTiles({
Promise.all(
specs.map((spec) =>
get(`/teams/${spec.id}/people`, { ttl }).then((data: TeamResponse) => ({
get<TeamResponse>(`/teams/${spec.id}/people`, { ttl }).then((data) => ({
spec,
data,
})),
@ -198,8 +198,8 @@ export default function PeopleTiles({
let live = true;
setFailed(false);
get(`/people?ids=${encodeURIComponent(slugKey)}`, { ttl })
.then((data: { people: Person[] }) => {
get<{ people: Person[] }>(`/people?ids=${encodeURIComponent(slugKey)}`, { ttl })
.then((data) => {
if (!live) return;
const byId: Record<string, Person> = {};
for (const person of data.people) byId[String(person.id)] = person;
@ -304,11 +304,10 @@ function resolveAll(
}
const { peopleslug, ...overrides } = entry;
const merged: Person = { ...base };
for (const [key, value] of Object.entries(overrides)) {
if (value !== undefined) (merged as Record<string, unknown>)[key] = value;
}
resolved.push(merged);
const defined: Partial<Person> = Object.fromEntries(
Object.entries(overrides).filter(([, value]) => value !== undefined),
);
resolved.push({ ...base, ...defined });
}
return resolved;