JSDoc
Add JSDoc only where a careful reader cannot infer intent, constraints, or failure modes from names and types alone. Prefer TypeScript types for shape; use JSDoc for why, when, and what breaks.
When to Document
Document a symbol when any of these are true:
- Control flow, algorithm, or state machine is non-obvious on first look.
- Behavior depends on invariants, ordering, timing, idempotency, or concurrency.
- Side effects matter (I/O, mutation, cache, network, timers, global state).
- Failure modes, throws, empty results, or partial success are part of the contract.
- Units, ranges, formats, or domain meanings are not clear from the type.
- Public / exported API that callers will use without reading the implementation.
- Deprecation, migration, security, or compatibility constraints apply.
When Not to Document
Skip JSDoc when:
- The name + TypeScript types already explain the symbol.
- The body is a trivial getter, setter, passthrough, or one-liner map/filter.
- The comment would only restate the parameter or return type.
- The comment narrates what the next line does (
// increment i).
- Generated code, tests that are self-describing fixtures, or vendored files (unless documenting a public test helper).
Default: no comment. Silence is better than noise.
TypeScript Rules
- Types carry the shape. Do not duplicate types in JSDoc (
@param {string} id) when the signature already has id: string.
- JSDoc carries meaning. Use prose + selective tags for behavior types cannot express.
- Prefer
@param name / @returns descriptions without type braces when documenting TS.
- Keep the first sentence a summary of behavior or purpose, not a restatement of the symbol name.
- Document non-obvious generics with a short note on what
T represents and any constraints beyond the type bound.
- For overloads, document each distinct call pattern; put shared caveats on the implementation or the primary export.
- Match existing project JSDoc style (tag set, punctuation,
@returns vs @return) when one is already dominant.
Required Content for Documented Symbols
Every JSDoc block you add must include:
- Summary — one sentence: what it does or why it exists (not “This function…” fluff).
- Non-obvious details — only what a reader would miss: invariants, ordering, side effects, edge cases, units, security.
Add tags only when they earn their keep:
| Tag |
Use when |
@param |
Param semantics, units, valid ranges, or “must be…” constraints beyond the type |
@returns |
Meaning of the value, empty/sentinel cases, or “never returns” style contracts |
@throws |
Documented error conditions callers should handle |
@example |
Non-trivial usage that types alone do not teach (keep short; one example usually enough) |
@see |
Related symbol, RFC, ticket, or algorithm source |
@deprecated |
Replacement path and removal intent |
@template |
Only in JS files or when documenting a generic’s role; prefer TS type params in .ts |
Do not invent tags the project never uses. Prefer standard JSDoc/TS-supported tags.
Workflow
- Scope — files, symbols, or “public API only” as the user named. If unclear, prefer exported / complex symbols over private helpers.
- Scan — find candidates using the “When to Document” list. Skip obvious code.
- Audit existing JSDoc — remove or rewrite comments that restate types, lie about behavior, or narrate the obvious.
- Write — add concise blocks; prefer editing the symbol in place over separate doc files.
- Verify — re-read: would a new teammate understand the hard parts without opening every callee? Types still match the prose?
Quality Bar
Good JSDoc:
- Explains a constraint or failure mode you cannot see from the signature.
- Stays accurate if implementation details change under the same contract.
- Is shorter than the code it documents whenever possible.
Bad JSDoc:
@param id - The id
@returns {Promise<User>} when the signature already says that
- Essays that duplicate the function body
- Outdated comments that contradict the code (delete or fix; never leave lying docs)
Examples
Concrete good/bad patterns: examples.md.
Completion
When asked to document a scope, report briefly:
- What was documented and why it qualified.
- What was left undocumented (and that it was intentional).
- Any JSDoc removed as noise or corrected as wrong.
1---2name: jsdoc3description: Enforces purposeful JSDoc on complex or non-obvious TypeScript code—algorithms, invariants, side effects, edge cases, and public contracts—without restating types or narrating simple code. Use when writing or reviewing TypeScript, adding documentation comments, cleaning noisy JSDoc, documenting public APIs, or when the user says jsdoc, JSDoc, document this, or add docs comments.4---56# JSDoc78Add JSDoc only where a careful reader cannot infer intent, constraints, or failure modes from names and types alone. Prefer TypeScript types for shape; use JSDoc for *why*, *when*, and *what breaks*.910## When to Document1112Document a symbol when **any** of these are true:1314- Control flow, algorithm, or state machine is non-obvious on first look.15- Behavior depends on invariants, ordering, timing, idempotency, or concurrency.16- Side effects matter (I/O, mutation, cache, network, timers, global state).17- Failure modes, throws, empty results, or partial success are part of the contract.18- Units, ranges, formats, or domain meanings are not clear from the type.19- Public / exported API that callers will use without reading the implementation.20- Deprecation, migration, security, or compatibility constraints apply.2122## When Not to Document2324Skip JSDoc when:2526- The name + TypeScript types already explain the symbol.27- The body is a trivial getter, setter, passthrough, or one-liner map/filter.28- The comment would only restate the parameter or return type.29- The comment narrates what the next line does (`// increment i`).30- Generated code, tests that are self-describing fixtures, or vendored files (unless documenting a public test helper).3132Default: **no comment**. Silence is better than noise.3334## TypeScript Rules35361. **Types carry the shape.** Do not duplicate types in JSDoc (`@param {string} id`) when the signature already has `id: string`.372. **JSDoc carries meaning.** Use prose + selective tags for behavior types cannot express.383. Prefer `@param name` / `@returns` **descriptions** without type braces when documenting TS.394. Keep the first sentence a summary of behavior or purpose, not a restatement of the symbol name.405. Document non-obvious generics with a short note on what `T` represents and any constraints beyond the type bound.416. For overloads, document each distinct call pattern; put shared caveats on the implementation or the primary export.427. Match existing project JSDoc style (tag set, punctuation, `@returns` vs `@return`) when one is already dominant.4344## Required Content for Documented Symbols4546Every JSDoc block you add must include:47481. **Summary** — one sentence: what it does or why it exists (not “This function…” fluff).492. **Non-obvious details** — only what a reader would miss: invariants, ordering, side effects, edge cases, units, security.5051Add tags only when they earn their keep:5253| Tag | Use when |54| --- | --- |55| `@param` | Param semantics, units, valid ranges, or “must be…” constraints beyond the type |56| `@returns` | Meaning of the value, empty/sentinel cases, or “never returns” style contracts |57| `@throws` | Documented error conditions callers should handle |58| `@example` | Non-trivial usage that types alone do not teach (keep short; one example usually enough) |59| `@see` | Related symbol, RFC, ticket, or algorithm source |60| `@deprecated` | Replacement path and removal intent |61| `@template` | Only in JS files or when documenting a generic’s *role*; prefer TS type params in `.ts` |6263Do not invent tags the project never uses. Prefer standard JSDoc/TS-supported tags.6465## Workflow66671. **Scope** — files, symbols, or “public API only” as the user named. If unclear, prefer exported / complex symbols over private helpers.682. **Scan** — find candidates using the “When to Document” list. Skip obvious code.693. **Audit existing JSDoc** — remove or rewrite comments that restate types, lie about behavior, or narrate the obvious.704. **Write** — add concise blocks; prefer editing the symbol in place over separate doc files.715. **Verify** — re-read: would a new teammate understand the hard parts without opening every callee? Types still match the prose?7273## Quality Bar7475Good JSDoc:7677- Explains a constraint or failure mode you cannot see from the signature.78- Stays accurate if implementation details change under the same contract.79- Is shorter than the code it documents whenever possible.8081Bad JSDoc:8283- `@param id - The id`84- `@returns {Promise<User>}` when the signature already says that85- Essays that duplicate the function body86- Outdated comments that contradict the code (delete or fix; never leave lying docs)8788## Examples8990Concrete good/bad patterns: [examples.md](references/examples.md).9192## Completion9394When asked to document a scope, report briefly:9596- What was documented and why it qualified.97- What was left undocumented (and that it was intentional).98- Any JSDoc removed as noise or corrected as wrong.