238 lines
6.8 KiB
Markdown
238 lines
6.8 KiB
Markdown
---
|
|
name: jsdoc
|
|
description: Guidelines for writing minimal, high-quality JSDoc comments in TypeScript.
|
|
---
|
|
|
|
# JSDoc Skill
|
|
|
|
This skill provides focused guidelines for writing JSDoc comments consistently across the codebase.
|
|
|
|
## When to Use
|
|
|
|
- Documenting exported type properties and configuration options
|
|
- Adding context that TypeScript types don't convey on their own
|
|
- Providing usage examples for non-obvious or multi-variant APIs
|
|
- Writing inline documentation for generated docs
|
|
|
|
## What It Does
|
|
|
|
- Defines `@example` format conventions (label + inline backtick or fenced block)
|
|
- Ensures every exported type and property has meaningful documentation
|
|
- Avoids redundant tags that duplicate TypeScript type information
|
|
- Ensures consistent documentation style across all packages
|
|
|
|
---
|
|
|
|
## `@example` Format
|
|
|
|
### Short one-liner — label on the `@example` line, code as inline backtick on the next line
|
|
|
|
```typescript
|
|
/**
|
|
* @example Required parameter
|
|
* `name: Type`
|
|
*
|
|
* @example Optional parameter
|
|
* `name?: Type`
|
|
*/
|
|
```
|
|
|
|
### Multi-line — fenced code block immediately after `@example`
|
|
|
|
````typescript
|
|
/**
|
|
* @example
|
|
* ```ts
|
|
* const result = buildParams(node, {
|
|
* paramsType: 'inline',
|
|
* })
|
|
* ```
|
|
*/
|
|
````
|
|
|
|
### Multiple variants — use multiple `@example` blocks
|
|
|
|
```typescript
|
|
/**
|
|
* @example Object mode
|
|
* `{ id, data, params }: { id: string; data: Data; params?: QueryParams }`
|
|
*
|
|
* @example Inline mode
|
|
* `id: string, data: Data, params?: QueryParams`
|
|
*/
|
|
```
|
|
|
|
### Rules
|
|
|
|
| Rule | ✅ Correct | ❌ Incorrect |
|
|
| ----------------------- | ----------------------------------- | -------------------------------------------- |
|
|
| Label + inline code | `@example Required\n\`name: Type\`` | `@example \`name: Type\`` (code on tag line) |
|
|
| Multi-line code | Fenced ` ```ts ``` ` block | Bare code lines without a fence |
|
|
| Short examples | Inline backtick | Triple-backtick fence (too heavy) |
|
|
| One concern per example | Separate `@example` blocks | One example covering all cases |
|
|
|
|
---
|
|
|
|
## Tags
|
|
|
|
### Use Frequently
|
|
|
|
| Tag | Purpose | Notes |
|
|
| ------------- | ------------------ | ------------------------------------------------------ |
|
|
| `@default` | Default value | Only when default is non-obvious; omit for `undefined` |
|
|
| `@example` | Usage example | Prefer for complex or multi-variant APIs |
|
|
| `@note` | Important caveat | Version info, breaking changes |
|
|
| `@deprecated` | Mark as deprecated | Include migration path |
|
|
|
|
### Use Sparingly
|
|
|
|
| Tag | Purpose |
|
|
| ----------- | ----------------------- |
|
|
| `@see` | Reference external docs |
|
|
| `@internal` | Internal API |
|
|
| `@beta` | Experimental |
|
|
|
|
### Avoid (TypeScript Provides)
|
|
|
|
- ❌ `@param` — use TypeScript parameter types
|
|
- ❌ `@returns` — use TypeScript return type
|
|
- ❌ `@type` — use TypeScript type annotation
|
|
- ❌ `@typedef` — use `type` or `interface`
|
|
- ❌ `@default undefined` — optional (`?`) already implies this
|
|
|
|
---
|
|
|
|
## Documentation Patterns
|
|
|
|
### Simple property — always multi-line
|
|
|
|
```typescript
|
|
/**
|
|
* Output directory for generated files.
|
|
*/
|
|
outDir?: string
|
|
```
|
|
|
|
> ❌ Never use single-line `/** description */` — always expand to multi-line.
|
|
|
|
### Property with non-obvious default
|
|
|
|
```typescript
|
|
/**
|
|
* Maximum number of concurrent callbacks during traversal.
|
|
* Higher values overlap I/O-bound work; lower values reduce memory pressure.
|
|
*
|
|
* @default 30
|
|
*/
|
|
concurrency?: number
|
|
```
|
|
|
|
> Do **not** add `@default false` or `@default undefined` when the TypeScript type already makes the default obvious.
|
|
|
|
### Enum / union with options
|
|
|
|
```typescript
|
|
/**
|
|
* How path parameters are emitted in the function signature.
|
|
* - `'object'` groups them as a single destructured parameter
|
|
* - `'inline'` spreads them as individual parameters
|
|
* - `'inlineSpread'` emits a single rest parameter
|
|
*/
|
|
pathParamsType: 'object' | 'inline' | 'inlineSpread'
|
|
```
|
|
|
|
### Property with example
|
|
|
|
```typescript
|
|
/**
|
|
* Applies a uniform transformation to every resolved type string.
|
|
* Use this for framework-level type wrappers.
|
|
*
|
|
* @example Wrap every type in a reactive container
|
|
* `typeWrapper: (t) => \`Reactive<${t}>\``
|
|
*/
|
|
typeWrapper?: (type: string) => string
|
|
```
|
|
|
|
### Nested properties — every field gets its own multi-line JSDoc
|
|
|
|
```typescript
|
|
names?: {
|
|
/**
|
|
* Name for the request body parameter.
|
|
* @default 'data'
|
|
*/
|
|
data?: string
|
|
/**
|
|
* Name for the query parameters group parameter.
|
|
* @default 'params'
|
|
*/
|
|
params?: string
|
|
/**
|
|
* Name for the header parameters group parameter.
|
|
* @default 'headers'
|
|
*/
|
|
headers?: string
|
|
}
|
|
```
|
|
|
|
### Function documentation
|
|
|
|
Only add JSDoc when it adds value beyond the signature:
|
|
|
|
```typescript
|
|
// ✅ No JSDoc needed — signature is self-explanatory
|
|
function camelCase(str: string): string { ... }
|
|
|
|
// ✅ JSDoc adds value — explains behaviour and non-obvious edge cases
|
|
/**
|
|
* Returns `true` when the schema resolves to a plain string output.
|
|
*
|
|
* - `string`, `uuid`, `email`, `url`, `datetime` are always plain strings.
|
|
* - `date` and `time` are plain strings when their `representation` is `'string'`.
|
|
*
|
|
* @example UUID resolves to a plain string
|
|
* `isStringType(uuidSchema) // true`
|
|
*
|
|
* @example Date with date representation is not a plain string
|
|
* `isStringType(dateSchema) // false`
|
|
*/
|
|
function isStringType(node: SchemaNode): boolean { ... }
|
|
```
|
|
|
|
---
|
|
|
|
## Guidelines
|
|
|
|
**✅ DO:**
|
|
|
|
- Document **what** the property does, not its TypeScript type
|
|
- Give every exported type, property, and function a JSDoc comment
|
|
- Always use multi-line JSDoc blocks — never single-line `/** ... */`
|
|
- Use concrete, full-sentence descriptions — not "Enum schema." or "Boolean value."
|
|
- Include `@default` only when the default is non-obvious (not `undefined`, not `false`)
|
|
- Use multiple `@example` blocks to show different variants or modes
|
|
- Keep `@example` labels short and descriptive
|
|
|
|
**❌ DON'T:**
|
|
|
|
- Write single-line `/** description */` — always use multi-line
|
|
- Write `@default undefined` — optional `?` already implies this
|
|
- Put code directly on the `@example` line: `@example \`foo: string\`` → move code to next line
|
|
- Use `@param` or `@returns` tags
|
|
- Over-document trivial, self-explanatory properties
|
|
|
|
---
|
|
|
|
## Tag Order
|
|
|
|
For consistency, use this order within a JSDoc block:
|
|
|
|
1. Description (required)
|
|
2. Bullet-list of variants or behaviours (if applicable)
|
|
3. `@default` (if non-obvious)
|
|
4. `@example` (one or more)
|
|
5. `@note` (if needed)
|
|
6. `@deprecated` (if applicable)
|
|
7. `@see` (if providing references)
|