pattern-engineer-typescript
Skill0 starsChanged 5 months agoMITView on GitHub
TypeScript bullets: `strict` + `noUncheckedIndexedAccess` + `exactOptionalPropertyTypes` + the no-implicit/no-fallthrough flags; no `any` (use `unknown` at boundaries, narrow); no `!` without a documented invariant; `type` for unions, `interface` for extendable shapes; discriminated unions; wrap `JSON.parse`; never `forEach(async)`; schema-validate untrusted objects before merge; explicit return types on public exports. Activate when editing TypeScript or `tsconfig.json`.
In this repository74 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- create-bug-issueSkill
- create-enhancement-issueSkill
- create-feature-issuesSkill
- dream-summary-memorySkill
- memory-conventionSkill
- operation-gitSkill
- pattern-architect-api-endpointSkill
- pattern-architect-data-modelSkill
- pattern-architect-deep-moduleSkill
- pattern-e2e-coding-standardSkill
- pattern-engineer-apiSkill
- pattern-engineer-backend-standardSkill
- pattern-engineer-coding-standardSkill
- pattern-engineer-containerSkill
- pattern-engineer-databaseSkill
- pattern-engineer-fastapiSkill
- pattern-engineer-frontend-standardSkill
- pattern-engineer-goSkill
- pattern-engineer-javaSkill
- pattern-engineer-kotlinSkill
- pattern-engineer-nodeSkill
- pattern-engineer-non-functionalSkill
- pattern-engineer-observabilitySkill
- pattern-engineer-pythonSkill
- pattern-engineer-rustSkill
- pattern-engineer-securitySkill
- pattern-engineer-ssrSkill
- pattern-engineer-swiftSkill
- pattern-engineer-viteSkill
- pattern-exploratory-testingSkill
- pattern-reviewer-apiSkill
- pattern-reviewer-backend-standardSkill
- pattern-reviewer-coding-standardSkill
- pattern-reviewer-containerSkill
- pattern-reviewer-contractSkill
- pattern-reviewer-databaseSkill
- pattern-reviewer-fastapiSkill
- pattern-reviewer-frontend-standardSkill
- pattern-reviewer-goSkill
- pattern-reviewer-javaSkill
- pattern-reviewer-kotlinSkill
- pattern-reviewer-nodeSkill
- pattern-reviewer-non-functionalSkill
- pattern-reviewer-observabilitySkill
- pattern-reviewer-pythonSkill
- pattern-reviewer-rustSkill
- pattern-reviewer-securitySkill
- pattern-reviewer-ssrSkill
- pattern-reviewer-swiftSkill
- pattern-reviewer-test-coverageSkill
- pattern-reviewer-typescriptSkill
- pattern-reviewer-viteSkill
- pattern-test-coverageSkill
- principle-engineer-tddSkill
- scaffold-projectSkill
- workflow-architect-interviewSkill
- workflow-designer-sample-pagesSkill
- workflow-design-interviewSkill
- workflow-e2e-authorSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 0 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 14
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-typescript.md in the consuming project (resolve …
- Very specific: line 32
No
any: Use unknown at boundaries (external input, JSON parsing, dynamic imports). - Very specific: line 42
Run npx biome check --write .
- Very specific: line 43
Use path aliases (@/components/Foo) from tsconfig.paths.
- Very specific: line 50
Prefer narrowing via discriminant property (if (msg.kind === "error")) over instanceof for tagged unions.
- Very specific: line 55
Don't add generics "for flexibility" if no caller benefits — the unused generic parameter becomes unknown and dilutes type safety.
- Very specific: line 60
Don't throw non-Error values.
- Very specific: line 66
Use === / !==; == does implicit coercion (0 == '', null == undefined) and is almost never what you want.
- Very specific: line 69
Never merge an untrusted object into a target without schema validation (prototype pollution).
- Very specific: line 76
FunctionandObject: Avoid; use (...args: never[]) => unknown and Record<string, unknown> (or a narrower shape). - Very specific: line 78
Mixing
import typewith runtime imports: Use import type { Foo } for type-only.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
pattern-engineer-typescript
When to activate
Activate when editing any .ts / .tsx file, tsconfig.json, type-only declarations, generics, or TypeScript-specific tooling (tsc, biome's TS rules). Applies to both frontend and Node/TS backend code. Skip for .js / .jsx files in JS-only projects.
Project memory overlay
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-typescript.md in the consuming project (resolve MAIN_ROOT="$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")"). If present, load it as an additive overlay to the rules below; if absent, skip silently. See memory-convention for the full contract (additivity, severity floor, conflict surfacing).
Patterns
tsconfig — non-negotiable flags
Copy the block in templates/tsconfig.json into the project's tsconfig.json. The required compilerOptions:
"strict": true— enablesstrictNullChecks,noImplicitAny, and friends in one knob."noUncheckedIndexedAccess": true—arr[i]isT | undefined, notT. Forces an explicit narrow before use."exactOptionalPropertyTypes": true—{ x?: string }isstring | undefined, notstring | undefined | unset. No silentundefinedin places that should be missing-key."noImplicitReturns": true— every branch in a function returns."noFallthroughCasesInSwitch": true—switchcases mustbreak/return/throw."noImplicitOverride": true— method overrides require theoverridekeyword."types": [...]— include the test-matcher types your tests use (@testing-library/jest-dom,vitest/globals). Land thetypesentry alongside (or one chore-scoped commit before) the first test that uses those matchers — without it,tsc --noEmitfails the Docker build.
Type discipline
- No
any. Useunknownat boundaries (external input, JSON parsing, dynamic imports); narrow with a type guard before use. - No
!non-null assertion unless paired with an inline comment explaining the invariant that guarantees non-null at that point (e.g.,enabled: !!groupIdupstream). typefor unions / intersections / mapped types.interfacefor object shapes that consumers may extend.- Discriminated unions over "together" optional fields.
{ status: "success"; data: T } | { status: "error"; error: Error }over{ data?: T; error?: Error }. Exhaustiveswitchchecking comes for free. - Brand primitive types when the value carries an invariant.
type UserId = number & { readonly __brand: 'UserId' }beats rawnumberonce a value crosses module boundaries. - Type props explicitly.
function Component(props: Props)over relying on inference for the public API.
Imports + module shape
- Don't hand-order imports. Biome's
organizeImportsowns the order — stdlib → third-party →@/...alias → relative; sorted within each group. - Run
npx biome check --write .after non-trivial edits so the import block matches whatassist/source/organizeImportsexpects (biome v2 moved import-organizing from a lint rule to an assist action; the command is unchanged). - Use path aliases (
@/components/Foo) fromtsconfig.paths; mirror invite.config.ts/vitest.config.tsso test runs resolve them. - Re-export sparingly. Barrel files (
index.tsthat re-exports) are fine for a public API surface; gratuitous re-exports leak into the bundle.
unknown and narrowing
- Parsed JSON,
localStoragereads,fetch().json()results all start asunknown. Validate with a Zod schema (or a hand-rolled type guard) at the boundary. - Type guards return
value is T:function isUser(x: unknown): x is User { return … }. - Prefer narrowing via discriminant property (
if (msg.kind === "error")) overinstanceoffor tagged unions.
Generics
- Constrain generic parameters when the function relies on a property:
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>. - Don't add generics "for flexibility" if no caller benefits — the unused generic parameter becomes
unknownand dilutes type safety.
Errors
- Native
Erroris fine for ad-hoc throws; subclassErrorwhen callers need to discriminate (AuthError,ValidationError). - Don't
thrownon-Error values;unknownthrown is a productivity tax for every catcher. - Type the catch parameter:
try { … } catch (err) { if (err instanceof AuthError) … }. - Wrap
JSON.parsein try/catch — invalid input throws and bubbles past most call sites silently.
Runtime correctness traps
- Use
===/!==;==does implicit coercion (0 == '',null == undefined) and is almost never what you want. - No
array.forEach(async fn)—forEachignores the returned promise. Usefor...offor sequential orawait Promise.all(array.map(...))for parallel. - No
fs.readFileSync/ sync I/O inside a request handler or any hot async path — blocks the event loop. - Never merge an untrusted object into a target without schema validation (prototype pollution).
Object.assign(target, JSON.parse(req.body))is a vector; parse with Zod first. - Public exports get explicit return types — inference is fine for internal callers but a public seam without a stated return type drifts silently.
Common traps
anyinascasts.value as any as Tround-trips throughanyto launder the type. If you need it, the validation belongs upstream.- Empty interfaces.
interface Props {}matches everything — usually a forgotten extension; either delete or fill in. FunctionandObject. Avoid; use(...args: never[]) => unknownandRecord<string, unknown>(or a narrower shape).enumfor fixed strings. Modern TS prefersconstobject +keyof typeofor a literal union — fewer runtime artifacts.- Mixing
import typewith runtime imports. Useimport type { Foo }for type-only; biome will rewriteimport { type Foo }consistently.
Templates
| Asset | Purpose |
templates/tsconfig.json | Drop-in compilerOptions with the project's required strictness flags + types entries; copy into the project's tsconfig.json and layer project-specific options on top. |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

