AGENTS.typescript.md — TypeScript and JavaScript
Additive to ../AGENTS.md. Applies to every .ts, .tsx, .js, .jsx,
.mjs and .cjs file, browser or Node. React rules are in AGENTS.react.md.
Build and check
<pm> run lint # ESLint with --max-warnings=0
<pm> run typecheck # tsc --noEmit
<pm> run format:check # prettier --check .
<pm> test
<pm> is the package manager your lockfile names: pnpm-lock.yaml,
yarn.lock or package-lock.json. One lockfile per package. Never commit a
second one.
TypeScript rules
- New code is TypeScript with
strict: true. New.jsonly for config a tool requires in JS. The one exception isdocs/assets/site.js: the website has no toolchain on purpose, so it is hand-written JS held to the rules below. - No
any. Useunknownand narrow. Data from outside (fetch responses, JSON, env,postMessage, storage) is parsed with the repo’s schema validator at the boundary before it gets a type. - No
@ts-ignoreor@ts-nocheck.@ts-expect-errorwith a reason, only where a library’s types are wrong. - No non-null
!to quiet the compiler. Same rule as Kotlin!!and Swift!. eslint-disableis line-scoped and carries a-- reason.- Discriminated unions for state (
{ status: 'loading' } | { status: 'ok'; data }), not a pile of booleans. Branded types for identifiers. - No floating promises.
async/awaitover.thenchains. - ESM
import/exportonly. Named exports, except where a framework requires a default export. - No
console.login shipped code. Use the repo’s logger.
Node rules
- The Node version is pinned in
.nvmrc; CI reads it. - Environment variables are read and validated once, in one config module.
Nothing else touches
process.env. - Web-standard APIs first: global
fetch,URL,AbortController. No second HTTP client (base rule).
Dependencies
- A
package.jsondependency change ships with its lockfile change, and the reverse. The dependency gate checks both. - No
latest, no git URLs, nofile:outside workspace packages. - A browser dependency answers the bundle-size question in the dependency gate.
Testing
- The repo’s runner (Vitest or Jest). Mock the network at the
fetchboundary, not by mocking your own modules. - A bug fix lands with a test that fails before the fix.
Anti-patterns seen in this repo
ascasts on parsed JSON instead of validating it.- Barrel files (
index.tsre-exporting a whole folder) that break tree-shaking.