Skip to content
Development documentation for the next release. Not a published package edition.
TSDoc formatting rules

TSDoc formatting rules

Rules and changes made to source files so TypeDoc renders correctly. Applies to typedoc@0.28 + typedoc-plugin-markdown@4.10.


Config (typedoc.json)

{
  "plugin": ["typedoc-plugin-markdown"],
  "entryPoints": ["./src/types/err.ts", ...],
  "out": "docs/api",
  "outputFileStrategy": "modules",
  "entryFileName": "README.md",
  "excludePrivate": true,
  "excludeInternal": true
}

Key decisions:

  • entryPoints — individual source files, not the barrel index.ts. Using the barrel collapses everything into one file.
  • outputFileStrategy: "modules" — one markdown file per source module.
  • entryFileName: "README.md" — the generated overview/index is docs/api/README.md (not index.md), consistent with GitHub directory browsing conventions.
  • excludeInternal: true — hides members tagged @internal. See the overload rule below for how this interacts with TypeScript overloads.

Rules

1. Module naming — require @module <name>

TypeDoc derives output filenames from the module name. Without an explicit @module tag, modules in subdirectories get a path-prefixed filename (types.outcome.md instead of outcome.md).

Every source file must have a standalone module comment with @module:

/**
 * Module description text.
 *
 * @module outcome
 */

The @module tag must appear in a free-floating comment — one not immediately followed by a declaration. Placing it at the end of the file-level introductory block is the standard pattern.

Files and their required tags:

FileTag
src/types/err.ts@module err
src/types/outcome.ts@module outcome
src/utils/format_dt.ts@module format_dt
src/utils/logger.ts@module logger

2. No @fileoverview — use plain description text

@fileoverview is a JSDoc convention but TypeDoc does not recognise it and emits a warning. TypeDoc automatically uses the text content of a free-floating module-level comment as the module description — no tag is needed.

Before (produces warning):

/**
 * @fileoverview Error-as-value implementation for TypeScript applications.
 *
 * This module provides...
 *
 * @module err
 */

After (no warning):

/**
 * Error-as-value implementation for TypeScript applications.
 *
 * This module provides...
 *
 * @module err
 */

3. Overload implementations — use /* */ not /** */

TypeDoc’s excludeInternal: true operates at the symbol level, not the signature level. When the implementation signature of an overloaded method carries @internal in a JSDoc block comment (/** ... */), TypeDoc excludes the entire method — including all public overload signatures.

Fix: change the JSDoc block comment (/** */) on implementation signatures to a regular block comment (/* */). The @internal tag inside a non-JSDoc comment is invisible to TypeDoc.

Before — all overloads hidden from docs:

defaultTo(fallback: T): T;
defaultTo(handler: (error: Err) => T): T;
defaultTo(fallback: T, asValue: true): T;

/**
 * Implementation for defaultTo overloads.
 * @internal
 */
defaultTo(fallbackOrHandler: T | ((error: Err) => T), asValue?: boolean): T {

After — public overloads visible, implementation hidden:

defaultTo(fallback: T): T;
defaultTo(handler: (error: Err) => T): T;
defaultTo(fallback: T, asValue: true): T;

/* Implementation for defaultTo overloads. */
defaultTo(fallbackOrHandler: T | ((error: Err) => T), asValue?: boolean): T {

This pattern was applied to four methods in src/types/outcome.ts:

MethodLocation
Outcome.err()static factory
Outcome.defaultTo()instance method
Outcome.pipe()instance method
Outcome.pipeAsync()instance method

private members are unaffected — TypeDoc excludes them via excludePrivate: true regardless of @internal. The @internal tag on private constructors and private static methods is harmless but redundant.


Layout

docs/
├── api/               ← generated by `bun run gen_docs` (do not edit)
│   ├── README.md      ← module index
│   ├── err.md
│   ├── format_dt.md
│   ├── logger.md
│   └── outcome.md
├── err.md             ← manual reference (hand-maintained)
├── format_dt.md
├── logger.md
├── logging_guide.md
├── outcome.md
└── tsdoc_guide.md     ← this file

The docs/api/ directory is fully regenerated on every gen_docs run. Manual docs in docs/ root are independent and unaffected.