JSDoc tag

@callback

  • Checked by TypeScript
  • Tested with TypeScript 5.9

@callback declares a named function type. The lines after it are ordinary @param and @returns tags, and together they describe the function's signature. TypeScript reads the block as type Rule = (value: string) => string | null, and the name works anywhere a type does.

Use it for the shape of a function that other code passes around: validators, event listeners, comparison functions, middleware. A @typedef with an arrow type does the same job on one line; @callback reads better when each parameter needs a description.

At a glance

Use JSDoc in a .js file TypeScript in a .ts file
A named function type /** * @callback Rule * @param {string} value * @returns {string | null} */ type Rule = (value: string) => string | null;
Using it /** @type {Rule} */ const required = (value) => …; const required: Rule = (value) => …;
A generic callback /** * @template T * @callback Listener * @param {T} payload */ type Listener<T> = (payload: T) => void;

Examples

validate.js validate.ts TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
/**
 * @callback Rule
 * @param {string} value
 * @returns {string | null} an error message, or null when the value is fine
 */

/** @type {Rule} */
const required = (value) => (value.trim() ? null : "Required");

/** @type {Rule} */
const shortEnough = (value) => (value.length <= 40 ? null : "40 characters at most");

/**
 * @param {string} value
 * @param {Rule[]} rules
 * @returns {string[]}
 */
export function validate(value, rules) {
  return rules.map((rule) => rule(value)).filter((message) => message !== null);
}

validate("Cotton tee", [required, shortEnough]);
type Rule = (value: string) => string | null;

const required: Rule = (value) => (value.trim() ? null : "Required");

const shortEnough: Rule = (value) => (value.length <= 40 ? null : "40 characters at most");

export function validate(value: string, rules: Rule[]): string[] {
  return rules.map((rule) => rule(value)).filter((message) => message !== null);
}

validate("Cotton tee", [required, shortEnough]);
Naming a function type with @callback.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
validate.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: validate.js(9,30): error TS2322: Type 'number' is not assignable to type 'string'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. validate.js(9,30): error TS2322: Type 'number' is not assignable to type 'string'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. validate.js(9,30): error TS2322: Type 'number' is not assignable to type 'string'. checked 21 October 2026
/**
 * @callback Rule
 * @param {string} value
 * @returns {string | null}
 */

/** @type {Rule} */
const maxLength = (value) => value.length;error TS2322: Type 'number' is not assignable to type 'string'.

export { maxLength };
A function that does not match the @callback type.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
events.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: events.js(22,33): error TS2322: Type 'string' is not assignable to type 'number'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. events.js(22,33): error TS2322: Type 'string' is not assignable to type 'number'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. events.js(22,33): error TS2322: Type 'string' is not assignable to type 'number'. checked 21 October 2026
/**
 * @template T
 * @callback Listener
 * @param {T} payload
 * @returns {void}
 */

/**
 * @template T
 * @param {Listener<T>[]} listeners
 * @param {T} payload
 */
export function emit(listeners, payload) {
  for (const listener of listeners) listener(payload);
}

/** @type {Listener<{ sku: string, quantity: number }>} */
const logAdd = (item) => console.log(`${item.quantity} × ${item.sku}`);

emit([logAdd], { sku: "TEE-01", quantity: 2 });
emit([logAdd], { sku: "TEE-01", quantity: "2" });error TS2322: Type 'string' is not assignable to type 'number'.
A generic @callback with @template.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Where the tag goes

A @callback block stands on its own in a /** */ comment; it does not need to sit above any code. Its name is visible in the whole file and, in a module, can be imported by other files with @import or import("./file.js").Rule.

Apply it with @type {Rule} on a variable, or use Rule inside other types: @param {Rule[]} rules. A function typed this way gets its parameter types from the callback, so (value) => … needs no @param of its own.

Generic callbacks

Put @template T in the same comment, before @callback, to make the callback generic. Listener<{ sku: string, quantity: number }> then fixes the payload type, and a call with the wrong payload is an error, as the third example shows.

@callback or @typedef?

/** @typedef {(value: string) => string | null} Rule */ declares the same type. Choose @callback when the parameters deserve a sentence each, since each @param line can carry a description that editors show while you type the arguments.

Gotchas

  • A @callback describes one call signature. For a function with properties as well (a function object with .displayName, say), use a @typedef with an object type that has a call signature: {{ (value: string): string, displayName: string }}.
  • @returns is optional in a callback. Without it, the return type is any, which accepts anything a function returns and lets callers use the result as anything; write @returns {void} when the result is ignored.

Questions

How do I type a function parameter in JSDoc?

Either inline, @param {(value: string) => boolean} test, or with a named type from @callback or @typedef. The named type is easier to reuse and to read in error messages.

Sources

Last reviewed 20 October 2026.