This skill should be used when the user asks to "add JSDoc", "document this function", "write JSDoc comments", "link to a type", "use @link tag", "hyperlink in JSDoc", "reference external service in docs", or needs guidance on JSDoc syntax, clickable type references, or TypeScript-optimized documentation.
/plugin marketplace add jasonkuhrt/claude-marketplace/plugin install typescript@jasonkuhrtThis skill inherits all available tools. When active, it can use any tool Claude has access to.
limitations.mdTypeScript-optimized JSDoc documentation guidance. TypeScript provides types; JSDoc provides meaning.
TypeScript already has complete type information. Never duplicate it in JSDoc.
// ❌ BAD - Redundant type information
/**
* @param {string} name - The user's name
* @param {number} age - The user's age
* @returns {boolean} Whether the user is valid
*/
function isValidUser(name: string, age: number): boolean { ... }
// ✅ GOOD - Description only, types come from TS
/**
* Validates user meets minimum requirements.
* @param name - Display name (must be non-empty)
* @param age - Must be 13 or older
*/
function isValidUser(name: string, age: number): boolean { ... }
Forbidden in TS projects:
| Tag | Why Forbidden |
|---|---|
@type | TS has the type |
@param {Type} | TS has param types |
@returns {Type} | TS has return type |
@typedef | Use TS type or interface |
@callback | Use TS function types |
Document what TypeScript cannot express:
| Document | Example |
|---|---|
| Purpose/intent | "Validates user meets minimum requirements" |
| Constraints | "Must be non-empty", "Range: 0-100" |
| Side effects | "Writes to localStorage", "Mutates input" |
| Exceptions | @throws - TS doesn't track thrown errors |
| Defaults | @default - Runtime default values |
| Examples | @example - Usage patterns |
| Deprecation | @deprecated - Migration guidance |
| External refs | @see - Links to docs, specs |
Skip JSDoc entirely for:
getName() returning a name needs no docsget id() { return this._id; }export * as Name)export * from './foo')If a const implements an interface with JSDoc, don't repeat it on the const:
/** Creates a user validator. */
interface UserValidator {
validate(user: User): boolean;
}
// ❌ BAD - Duplicates interface JSDoc
/** Creates a user validator. */
const validator: UserValidator = { ... };
// ✅ GOOD - Interface JSDoc is inherited
const validator: UserValidator = { ... };
For export * as Name, use @ts-expect-error with duplicate namespace to add docs:
// @ts-expect-error Duplicate identifier
export * as Utils from './utils'
/** Utility functions for string manipulation. */
export namespace Utils {}
@throwsTypeScript doesn't track exceptions. Document them:
/**
* Parses JSON configuration file.
* @throws {SyntaxError} If JSON is malformed
* @throws {Error} If file doesn't exist
*/
function parseConfig(path: string): Config { ... }
@exampleShow usage patterns, especially for complex APIs:
/**
* Creates a debounced version of a function.
* @example
* const debouncedSave = debounce(save, 300);
* input.addEventListener('change', debouncedSave);
*/
function debounce<T extends (...args: any[]) => any>(fn: T, ms: number): T { ... }
@defaultDocument runtime defaults (complements TS default params):
interface Options {
/** @default 3000 */
timeout?: number
/** @default 'warn' */
logLevel?: 'debug' | 'info' | 'warn' | 'error'
}
@deprecatedAlways include migration path:
/**
* @deprecated Use {@link createUser} instead. Will be removed in v3.0.
*/
function addUser(name: string): User { ... }
@typeParam - Use SparinglyOnly document type parameters users explicitly provide:
// ✅ Document - user explicitly provides type
/**
* Creates a type-safe event emitter.
* @typeParam Events - Map of event names to payload types
* @example
* const emitter = createEmitter<{ click: MouseEvent; key: KeyboardEvent }>();
*/
function createEmitter<
Events extends Record<string, unknown>,
>(): Emitter<Events>
// ❌ Don't document - type is inferred from arguments
/**
* Returns first element of array.
*/
function first<T>(arr: T[]): T | undefined
{@link} TagCreate clickable references to types, functions, and identifiers.
/** Composes {@link RhythmMediaPlayPauseButton} and {@link RhythmMediaTimeDisplay}. */
/** Returns result from {@link audiosByPriority | the priority list}. */
For {@link Identifier} to be clickable, the identifier must be in scope:
| Scenario | Clickable? |
|---|---|
| Same file export | Yes |
| Imported type | Yes |
| Not imported | No (plain text) |
When a type is needed only for {@link}, use underscore prefix to avoid lint errors:
// For JSDoc {@link} only
import type { MuxAsset as _MuxAsset } from '@heartbeat/types';
/**
* Uploads audio to {@link _MuxAsset | Mux} for transcoding.
*/
export const uploadVoiceNote = async (blob: Blob) => { ... };
@see for Reference Docs/**
* Type-safe predicates for DOMException error types.
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMException
*/
/**
* Uploads audio to [Mux](https://www.mux.com/) for transcoding.
*/
| Use Case | Syntax |
|---|---|
| Link to identifier | {@link Identifier} |
| Link with text | {@link Identifier | display text} |
| External docs | @see https://... |
| Inline link | [Text](https://...) |
| Exception | @throws {ErrorType} Description |
| Example | @example + code block |
| Default value | @default value |
| Deprecation | @deprecated Use X instead |
| JSDoc-only import | import type { X as _X } |
{@link} requires identifier in scope (imported or same file)limitations.md for known TypeScript/IDE limitationsThis skill should be used when the user asks about libraries, frameworks, API references, or needs code examples. Activates for setup questions, code generation involving libraries, or mentions of specific frameworks like React, Vue, Next.js, Prisma, Supabase, etc.