| name | jsdoc-typescript-docs |
| description | Expert guidance for TypeScript/JSDoc documentation decisions. Use when (1) documenting public library APIs for consumers, (2) deciding what to document vs skip for different audiences, (3) writing documentation for complex types or error handling, (4) setting up automated documentation generation with TypeDoc, (5) creating migration guides for breaking changes. NOT for basic JSDoc syntax—only when making documentation strategy decisions. |
JSDoc TypeScript Documentation
Expert-level guidance for TypeScript documentation strategy and decision-making.
Documentation Decision Tree
| Code Type | Public Library | Internal Library | Personal/Small Team |
|---|
| Public function | Always: Full docs + examples + errors | Always: Brief + non-obvious behavior | If complex: Why + gotchas only |
| Public interface | Always: With usage example | Always: Brief description | If non-obvious: Purpose only |
| Type alias | Always: Purpose + example | If non-obvious: When to use | Skip: If name + types are clear |
| Private function | If complex: Algorithm explanation | If complex: Why it exists | Skip: Unless tricky |
| Generic param | Always: Constraint rationale | Always: What it represents | If constrained: Why constraint |
| Constants | If non-obvious: Why this value | If non-obvious: Why this value | Skip: Self-explanatory values |
| Error throws | Always: All possible errors | Always: Error codes/types | If non-obvious: What triggers |
Before Documenting, Ask
Audience: Who will read this?
- Library users (npm package) → Full docs: examples, edge cases, performance, migration guides
- Internal team (company-wide) → Focus on "why" decisions, gotchas, design context
- Future you (personal project) → Context for non-obvious choices, workarounds, TODOs
Value: Does the type system already say it?
- Types say WHAT → Document WHY and WHEN (behavior, constraints, use cases)
- Types unclear → Document WHAT first, then WHY
- Types complete → Skip redundant descriptions, document non-obvious behavior only
Maintenance: Will this stay synchronized?
- Stable contracts (public API) → Document thoroughly, changes require migration guides
- Implementation details → Don't document (will diverge), use code comments instead
- Behavior that changes → Document contract in JSDoc, validate in tests
Critical Anti-Patterns
NEVER: Document What Types Already Express
function getName(user: User): string {
return user.name;
}
Why: Wastes time, adds clutter, becomes outdated. Types already express this contract.
Instead: Only document if there's non-obvious behavior:
function getDisplayName(user: User): string {
return user.name || user.email.split('@')[0] || 'Anonymous';
}
NEVER: Skip Error Documentation in Public APIs
export async function fetchUser(id: string): Promise<User> {
}
Why: Consumers can't handle errors they don't know about. Leads to unhandled exceptions in production.
Instead: Document ALL possible errors:
export async function fetchUser(id: string): Promise<User> {
}
NEVER: Use Template/Placeholder Documentation
export function processData(data: any): any {
}
Why: Worse than no docs—suggests API is documented when it isn't. Misleads users.
Instead: Either document properly or omit JSDoc entirely:
export function processData(data: ProcessInput): ProcessResult {
}
NEVER: Document Internal Implementation in Public API
export async function getUsers(): Promise<User[]> {
}
Why: Locks you into implementation. Users depend on Redis, you can't switch to different cache.
Instead: Document observable behavior only:
export async function getUsers(): Promise<User[]> {
}
NEVER: Skip Migration Guides for Breaking Changes
export function createUser(data: NewUserData): Promise<User> {
}
Why: Users can't upgrade without knowing how to migrate.
Instead: Provide explicit migration path:
export function createUser(data: NewUserData): Promise<User> {
}
NEVER: Use Non-Executable Examples
export function myFunction(a: string, b: number): Result {
}
Why: Examples that don't run mislead users and break when API changes.
Instead: Use real, executable code:
export function myFunction(a: string, b: number): Result {
}
When to Load References
Load jsdoc-syntax.md when:
- Need specific JSDoc tag syntax (@param, @returns, @throws, etc.)
- Documenting overloaded functions or complex generics
- Need syntax for React components or classes
- Want comprehensive tag reference
Load library-api-docs.md when:
- MANDATORY: Documenting public library for external consumers
- MANDATORY: Writing documentation for npm package
- Need examples of audience-specific documentation depth
- Documenting breaking changes or deprecations
- Need performance documentation patterns
- Creating migration guides
Load typedoc-setup.md when:
- MANDATORY: Setting up automated documentation generation
- MANDATORY: Configuring TypeDoc for the first time
- Integrating documentation into CI/CD pipeline
- Configuring multi-package monorepo documentation
- Setting up GitHub Pages deployment
- Need documentation validation in pre-commit hooks
Quick Wins: High-Impact Documentation
Focus documentation effort on these high-value targets:
- Public API functions: 80% of user questions come from public functions
- Error conditions: Undocumented errors = production incidents
- Complex types: Generic types and conditional types need explanation
- Migration guides: Breaking changes without migration = angry users
- Performance characteristics: O(n²) operations need warnings
- Examples: One good example > 100 lines of prose
Documentation Smells (Warning Signs)
| Smell | What It Means | Fix |
|---|
| Every function has identical JSDoc | Template docs, not real docs | Remove templates, document non-obvious only |
| No @throws tags | Errors not documented | Add all possible exceptions |
| No examples in library | Theory without practice | Add real, executable examples |
| Docs contradict types | Out of sync | Update docs or simplify (let types speak) |
| Private functions have more docs than public | Inverted priorities | Focus on public API first |
TypeDoc Validation
Enforce documentation in CI:
{
"scripts": {
"docs:validate": "typedoc --validation.notDocumented true"
}
}
Pre-commit hook:
npm run docs:validate || exit 1
Resources