Learn

/

JSDoc

JSDoc

5 patterns

Documenting defaults, examples, and deprecations so consumers don't have to read your source.

Simple prop documentation
easy
Avoid
interface BadgeProps {
  label: string;
  variant: 'default' | 'success' | 'warning';
}

Prefer
interface BadgeProps {
  /** The text displayed inside the badge. */
  label: string;
  /**
   * The visual style variant of the badge.
   * @default 'default'
   */
  variant: 'default' | 'success' | 'warning';
}

Even simple props benefit from JSDoc. When another developer hovers over variant in their IDE, they instantly see what it does and what the default is. The @default tag is especially useful for optional props.

TypeScript: JSDoc Reference
Component documentation
medium
Avoid
interface TooltipProps {
  /** The content. */
  content: string;
  /** The children. */
  children: React.ReactNode;
  /** The position. */
  position?: 'top' | 'bottom';
  /** The delay. */
  delay?: number;
}

Prefer
interface TooltipProps {
  /** The text content displayed inside the tooltip. */
  content: string;
  /** The element that triggers the tooltip on hover. */
  children: React.ReactNode;
  /**
   * Where the tooltip appears relative to the trigger.
   * @default 'top'
   */
  position?: 'top' | 'bottom';
  /**
   * Delay in milliseconds before the tooltip appears.
   * @default 200
   */
  delay?: number;
}

Good JSDoc explains what a prop does and documents defaults. "The text content displayed inside the tooltip" is useful; "The content" just repeats the prop name.

The @default tags on optional props are especially valuable — no need to read the implementation to know the fallback.

TypeScript: JSDoc Reference
Callback prop documentation
medium
Avoid
interface DataTableProps<T> {
  /** The data to display. */
  data: T[];
  /** Handler for row clicks. */
  onRowClick?: (row: T) => void;
  /** Handler for sorting. */
  onSort?: (col: string) => void;
}

Prefer
interface DataTableProps<T> {
  /** The array of data objects to render as rows. */
  data: T[];
  /**
   * Called when a row is clicked.
   * Receives the full data object for the clicked row.
   */
  onRowClick?: (row: T) => void;
  /**
   * Called when a column header is clicked for sorting.
   * Receives the column key that was clicked.
   */
  onSort?: (columnKey: string) => void;
}

Good callback documentation explains when the callback fires and what the parameters represent. "Called when a column header is clicked for sorting" tells you the trigger. The rename from col to columnKey reinforces clarity. Compare "Handler for sorting" — that just restates the prop name.

TypeScript: JSDoc Reference
Realistic JSDoc examples
hard
Avoid
/**
 * A confirmation dialog component.
 *
 * @example
 * <ConfirmDialog
 *   title="Title"
 *   message="Message"
 *   onConfirm={handleConfirm}
 *   onCancel={handleCancel}
 * />
 */
interface ConfirmDialogProps {
  /** The title. */
  title: string;
  /** The message. */
  message: string;
  /** Confirm handler. */
  onConfirm: () => void;
  /** Cancel handler. */
  onCancel: () => void;
  /** The variant. */
  variant?: 'info' | 'danger';
}

Prefer
/**
 * A modal dialog that asks the user to confirm
 * or cancel a destructive action.
 *
 * @example
 * <ConfirmDialog
 *   title="Delete project?"
 *   message="This cannot be undone."
 *   variant="danger"
 *   onConfirm={handleDelete}
 *   onCancel={handleDismiss}
 * />
 */
interface ConfirmDialogProps {
  /** The heading text of the dialog. */
  title: string;
  /** The body message explaining the action. */
  message: string;
  /** Called when the user clicks the confirm button. */
  onConfirm: () => void;
  /** Called when the user dismisses or cancels. */
  onCancel: () => void;
  /**
   * Visual style of the dialog.
   * Use `'danger'` for destructive actions.
   * @default 'info'
   */
  variant?: 'info' | 'danger';
}

A good @example uses realistic prop values that show how the component is actually used. title="Delete project?" and variant="danger" paint a real scenario.

Prop-level JSDoc explains purpose, not just the name: "The heading text of the dialog" vs "The title."

JSDoc: @example tag
Deprecation notice in JSDoc
easy
Avoid
interface AccordionProps {
  // Don't use isOpen, use expanded instead
  isOpen?: boolean;
  expanded?: boolean;
  children: React.ReactNode;
  onToggle?: () => void;
}

Prefer
interface AccordionProps {
  /**
   * @deprecated Use `isExpanded` instead.
   * Will be removed in v3.0.
   */
  isOpen?: boolean;
  /** Whether the section is expanded. */
  isExpanded?: boolean;
  children: React.ReactNode;
  onToggle?: () => void;
}

The @deprecated JSDoc tag triggers a visual strikethrough in most IDEs and shows a warning on hover. It's machine-readable — linters can flag usage. A code comment is invisible at the call site and can't be enforced by tooling.

TypeScript: JSDoc Reference