TypeScript pack

Last updated

Cards specific to typescript. Use them with the level page that matches your input. Report each check as PASS, FAIL, or N/A with file:line evidence. A FAIL carries the card's severity. Any block FAIL means request changes. A should-fix or discuss FAIL goes in the review but does not block.

Verdict: request changes - change, function - 2 block, 1 should-fix FAIL, 1 PASS, 14 N/A
FAIL [block] chg-expand-contract - src/a.py:42 - renames the column and drops the old one in one migration
FAIL [block] svc-sqli-authn - src/db.py:88 - proven: builds the WHERE clause with an f-string from request.args
FAIL [should-fix] chg-one-concern - src/b.py:7 - a logging rewrite rides along with the bug fix
PASS chg-breaking-change-taxonomy - src/c.py:15 - no signature or return shape changes
N/A: 14 cards, applies_when does not hold
What the badges mean

Draft cards

No stable cards yet.

5 draft cards

A draft card is not vetted. Report a FAIL of one under Draft findings, at should-fix at most, never in the ledger or the verdict. How a draft becomes stable

typescript-mock-at-the-boundary

should-fixdrafttestingmaintainability

Applies when: A Vitest test calls vi.mock on a module of the project's own code.

Rule. Fake the system boundary (network, clock, storage), for example with Mock Service Worker; do not vi.mock your own modules when a boundary fake would do.

Why. A mocked internal module makes the test check the mock. The test then passes while the real wiring is broken, and fails on a harmless refactor.

FAIL
vi.mock('./api/client', () => ({ getUser: vi.fn().mockResolvedValue({ name: 'Ada' }) }));
PASS
import { http, HttpResponse } from 'msw';
server.use(http.get('/api/user', () => HttpResponse.json({ name: 'Ada' })));

Counterpoint. "Some internal seams are slow or nondeterministic." Mock those at their edge (the clock, the random source), not the module that uses them.

Why it is a draft: too few organisations back a clause of the Rule. Vitest and Testing Library state it; Testing Library's own project counts once and a third is missing How a draft becomes stable

Cites 2 organisations, backing unjudged:

typescript-no-floating-promises

should-fixdraftcorrectnessreliability

Applies when: TypeScript code calls an async function or creates a Promise.

Rule. Every Promise is awaited, returned, or given a .catch; enable @typescript-eslint/no-floating-promises.

Why. A Promise nobody handles turns a failure into an unhandled rejection, or into work that finishes after the code assumed it was done.

FAIL
async function onSave() {
  saveDraft(doc); // returns a Promise; errors vanish
  closeDialog();
}
PASS
async function onSave() {
  await saveDraft(doc);
  closeDialog();
}

Counterpoint. "Fire-and-forget is intended." Mark it with void saveDraft(doc).catch(report) so the choice is visible and failures are still reported.

Why it is a draft: it overlaps a stable card. The stable card fn-handle-rejected-promises covers unhandled rejections; merge or delete How a draft becomes stable

Tool gate: "@typescript-eslint/no-floating-promises"

Cites 1 organisation, backing unjudged:

typescript-partial-mock-keeps-original

should-fixdrafttestingcorrectness

Applies when: A vi.mock factory replaces a module that exports error classes, enums or constants the code under test also uses.

Rule. A vi.mock factory spreads await importOriginal() and overrides only what the test needs; never swap an exported error class for a stub.

Why. Code under test does err instanceof ApiError. If the mock exports a different or empty class, the check is false and the error path is never exercised.

FAIL
vi.mock('./errors', () => ({ ApiError: class {} , fetchUser: vi.fn() }));
PASS
vi.mock('./errors', async (importOriginal) => ({
  ...(await importOriginal<typeof import('./errors')>()),
  fetchUser: vi.fn(),
}));

Counterpoint. "The real module has side effects on import." Then mock the effect's boundary; a factory that drops half the exports breaks other callers.

Why it is a draft: too few organisations back a clause of the Rule. Only the Vitest docs describe importOriginal; the instanceof failure is not documented by a second organisation How a draft becomes stable

Cites 1 organisation, backing unjudged:

typescript-shared-test-setup

discussdrafttestingmaintainability

Applies when: Several Vitest test files repeat the same setup (i18n init, MSW server, DOM matchers).

Rule. Put setup that every test file repeats into one file listed in setupFiles, not into each test file.

Why. Copies drift: one file inits i18n with other resources and a test passes alone but fails in the suite. One file is one place to change.

FAIL
// a.test.tsx, b.test.tsx, c.test.tsx each start with:
import i18n from 'i18next';
i18n.init({ lng: 'en', resources });
PASS
// vitest.config.ts
export default defineConfig({ test: { setupFiles: ['./test/setup.ts'] } });
// test/setup.ts runs i18n.init once per test file

Counterpoint. "A global setup hides what a test needs." Keep the shared file to things every test needs; per-test data stays in the test.

Why it is a draft: too few organisations back a clause of the Rule. Only the Vitest docs state it; needs two more organisations How a draft becomes stable

Cites 1 organisation, backing unjudged:

typescript-strict-mode

should-fixdraftcorrectnessmaintainability

Applies when: The repository has a tsconfig.json.

Rule. tsconfig.json sets "strict": true; switch off a single strict flag only with a written reason.

Why. The strict family (null checks, implicit any, strict function types) is where most type errors that reach users are caught. Without it, tsc passing says little.

FAIL
{ "compilerOptions": { "target": "ES2022", "strict": false } }
PASS
{ "compilerOptions": { "target": "ES2022", "strict": true } }

Counterpoint. "Migrating a big codebase is too costly." Enable it per flag, or per package with project references, and ratchet; do not leave it off by default for new code.

Why it is a draft: too few organisations back a clause of the Rule. Only Microsoft's tsconfig reference states it; needs two more organisations How a draft becomes stable

Tool gate: tsc

Cites 1 organisation, backing unjudged: