---
name: tsdoc-comments
source: https://app.decimal.ai/s/tsdoc-comments@1/SKILL.md
source_sha256: 075fa2826c24
---

# TSDoc documentation comments

## Contract

Documentation comments on TypeScript declarations follow TSDoc: a `/** */` block that opens
with a prose summary, then block tags — `@param name - description` (a hyphen separator, and
NEVER a `{type}` brace, because the TypeScript signature already carries the type),
`@returns`, `@typeParam`, `@remarks`, `@example`, `@defaultValue`, `@deprecated` — one tag per
parameter, in signature order. Apply when writing or cleaning up doc comments on functions,
methods, classes, interfaces, and type aliases; not for docstrings in another language, prose
reference pages, or ordinary inline comments.

## Rules

1. **Block form.** A doc comment is a `/** ... */` block placed directly above the declaration
   it documents — not `//` line comments and not a plain `/* */` block. Interior lines
   conventionally begin with ` * `.

2. **Summary first.** The comment opens with a short prose summary of what the declaration
   does. Tags always come after the summary, never before it. Longer discussion belongs in a
   `@remarks` tag, not stuffed into the summary line.

3. **`@param` shape — hyphen, no type braces.** Document each parameter as
   `@param parameterName - description`. The hyphen between the name and the description is
   required. Do NOT add a `{type}` annotation: `@param {string} name` is the JSDoc form, not
   TSDoc — the parameter's declared type in the signature is the single source of truth. Emit
   exactly one `@param` per parameter, ordered to match the signature.

4. **`@returns`, spelled in full.** Document the return value with `@returns` (with the
   trailing `s`), in prose and, again, with no `{type}` brace. `@return` without the `s` is the
   JSDoc spelling and is wrong here. Omit the tag entirely for a `void` function rather than
   writing `@returns void`.

5. **Generics use `@typeParam`.** A generic type parameter is documented with
   `@typeParam T - description`, hyphen included. Not `@template` and not `@tparam` — those come
   from other toolchains.

6. **`@defaultValue` for defaults.** State the default of an optional parameter or property
   with `@defaultValue`, e.g. `@defaultValue 0`. Not `@default`.

7. **`@deprecated` carries a reason.** Mark a deprecated declaration with `@deprecated` plus a
   note saying what to use instead — not merely a sentence in the summary.

8. **`@example` for usage.** Runnable usage samples go under an `@example` tag, one fenced block
   each, rather than being narrated inside the summary.

9. **Tag order.** Summary → `@remarks` → `@typeParam` → `@param` (in signature order) →
   `@returns` → `@throws` → `@example` → `@deprecated`. Keep the parameter tags grouped and in
   order.

## Worked examples

A plain function — the JSDoc default, then the conforming TSDoc:

```ts
BEFORE
/**
 * @param {number} value the number to clamp
 * @param {number} min lower bound
 * @param {number} max upper bound
 * @return the clamped number
 */
function clamp(value: number, min: number, max: number): number { /* ... */ }
```

```ts
AFTER
/**
 * Restricts a number to an inclusive range.
 * @param value - the number to constrain
 * @param min - the lower bound
 * @param max - the upper bound
 * @returns the value pulled to the nearest bound when it falls outside the range
 */
function clamp(value: number, min: number, max: number): number { /* ... */ }
```

A generic function — `@template`/`@default` braces, then TSDoc:

```ts
BEFORE
/**
 * @template T
 * @param {T[]} items the array
 * @param {number} [size] chunk size
 * @default 10
 */
function chunk<T>(items: T[], size = 10): T[][] { /* ... */ }
```

```ts
AFTER
/**
 * Splits a list into consecutive fixed-length groups.
 * @typeParam T - the element type of the input list
 * @param items - the list to divide
 * @param size - the maximum length of each group
 * @defaultValue 10
 * @returns an array of groups, each holding at most `size` elements
 */
function chunk<T>(items: T[], size = 10): T[][] { /* ... */ }
```

A deprecation — prose aside, then a real `@deprecated` tag:

```ts
BEFORE
/** Old palette helper — don't use, call resolveColor instead. */
function legacyColor(name: string): string | undefined { /* ... */ }
```

```ts
AFTER
/**
 * Reads a named swatch from the legacy palette table.
 * @deprecated Use `resolveColor`, which honors theme overrides this ignores.
 * @param name - the palette key to look up
 * @returns the hex string, or `undefined` when the key is absent
 */
function legacyColor(name: string): string | undefined { /* ... */ }
```

A usage sample — narrated, then an `@example` block:

```ts
BEFORE
/** Formats an amount. Call it like formatMoney(9.5, 'USD'). */
function formatMoney(amount: number, currency: string): string { /* ... */ }
```

```ts
AFTER
/**
 * Formats a numeric amount as a localized currency string.
 * @param amount - the value to format
 * @param currency - the ISO 4217 code selecting the currency
 * @returns the formatted display string
 * @example
 * ```ts
 * formatMoney(9.5, "USD"); // "$9.50"
 * ```
 */
function formatMoney(amount: number, currency: string): string { /* ... */ }
```

## Edge cases & exceptions

- **`void` return** → omit `@returns` altogether; do not write `@returns void`.
- **Optional parameter** → still `@param name - ...`; the optionality lives in the signature
  (`name?`), not in a `@param [name]` bracket.
- **Rest parameter** → `@param values - ...`; the tag name carries no `...` prefix.
- **Destructured object parameter** → document the parameter once and describe its fields in
  the prose, rather than inventing a `@param options.field` tag per key.
- **Thrown errors** → a separate `@throws` tag naming the condition, not a note in `@returns`.
- **Cross-references** → link other symbols inline with `{@link OtherSymbol}` inside a
  description; it is a TSDoc inline tag, not free prose.

## Do / Don't

- Do put a hyphen after each parameter name. Don't run the name straight into the description.
- Do let the signature carry the types. Don't add `{type}` braces to any tag.
- Do write `@returns`. Don't write `@return`.
- Do document generics with `@typeParam`. Don't reach for `@template`.
- Do state defaults with `@defaultValue`. Don't write `@default`.
- Do open with a prose summary. Don't lead the comment with a tag.

## Common mistakes

- `@param {string} id - ...` — the JSDoc type brace that TSDoc drops.
- `@return` without the trailing `s`.
- `@template T` instead of `@typeParam T` for a generic.
- `@default 5` instead of `@defaultValue 5`.
- `@param id the identifier` — the missing hyphen separator.
- `@param [id] - ...` — the bracket-for-optional habit; optionality belongs in the signature.
- Leading the comment with `@param` and no summary sentence.
