JSDoc tag

@overload

  • Checked by TypeScript
  • Since TypeScript 5.0

@overload declares one call signature of a function. Write one JSDoc comment per signature, each starting with @overload and listing that signature's @param and @returns, then a last ordinary comment for the implementation. TypeScript 5.0 added the tag; it is the JavaScript spelling of TypeScript's overload declarations.

Callers see only the overloads. A call is checked against each in order, the first match decides the return type, and a call that matches none is an error (TS2769, "No overload matches this call").

At a glance

Use JSDoc in a .js file TypeScript in a .ts file
One overload /** * @overload * @param {string} sku * @returns {Product | undefined} */ function find(sku: string): Product | undefined;
The implementation /** @param {string | string[]} skuOrSkus */ function find(skuOrSkus) { … } function find(skuOrSkus: string | string[]) { … }

Examples

catalog.js catalog.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
/** @typedef {{ sku: string, name: string }} Product */

/** @type {Product[]} */
const products = [{ sku: "TEE-01", name: "Cotton tee" }];

/**
 * @overload
 * @param {string} sku
 * @returns {Product | undefined}
 */
/**
 * @overload
 * @param {string[]} skus
 * @returns {Product[]}
 */
/**
 * @param {string | string[]} skuOrSkus
 */
export function find(skuOrSkus) {
  if (Array.isArray(skuOrSkus)) return products.filter((p) => skuOrSkus.includes(p.sku));
  return products.find((p) => p.sku === skuOrSkus);
}

const one = find("TEE-01");
const many = find(["TEE-01", "MUG-07"]);
one?.name;
many.length;
type Product = { sku: string; name: string };

const products: Product[] = [{ sku: "TEE-01", name: "Cotton tee" }];

export function find(sku: string): Product | undefined;
export function find(skus: string[]): Product[];
export function find(skuOrSkus: string | string[]) {
  if (Array.isArray(skuOrSkus)) return products.filter((p) => skuOrSkus.includes(p.sku));
  return products.find((p) => p.sku === skuOrSkus);
}

const one = find("TEE-01");
const many = find(["TEE-01", "MUG-07"]);
one?.name;
many.length;
Two call signatures with @overload.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
catalog.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: catalog.js(19,11): error TS2769: No overload matches this call. Overload 1 of 2, '(sku: string): string', gave the following error. Argument of type 'number' is not assignable to parameter of type 'string'. Overload 2 of 2, '(skus: string[]): string[]', gave the following error. Argument of type 'number' is not assignable to parameter of type 'string[]'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. catalog.js(19,11): error TS2769: No overload matches this call. Overload 1 of 2, '(sku: string): string', gave the following error. Argument of type 'number' is not assignable to parameter of type 'string'. Overload 2 of 2, '(skus: string[]): string[]', gave the following error. Argument of type 'number' is not assignable to parameter of type 'string[]'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. catalog.js(19,11): error TS2769: No overload matches this call. The last overload gave the following error. Argument of type 'number' is not assignable to parameter of type 'string[]'. checked 21 October 2026
/**
 * @overload
 * @param {string} sku
 * @returns {string}
 */
/**
 * @overload
 * @param {string[]} skus
 * @returns {string[]}
 */
/**
 * @param {string | string[]} skuOrSkus
 */
export function normalize(skuOrSkus) {
  return Array.isArray(skuOrSkus) ? skuOrSkus.map((s) => s.toUpperCase()) : skuOrSkus.toUpperCase();
}

normalize(42);error TS2769: No overload matches this call.
  Overload 1 of 2, '(sku: string): string', gave the following error.
    Argument of type 'number' is not assignable to parameter of type 'string'.
  Overload 2 of 2, '(skus: string[]): string[]', gave the following error.
    Argument of type 'number' is not assignable to parameter of type 'string[]'.
A call that matches none of the overloads.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Where the tags go

All the comments sit above the one function declaration, overloads first. Each @overload comment is a complete signature: the parameters it lists are the parameters of that overload, even when they have other names than the implementation's.

The implementation's comment types the parameters the function actually receives, usually a union of the overloads' types. Its signature is hidden from callers, as in TypeScript.

When to use it

Use overloads when the return type depends on the argument type in a way a union cannot express: one SKU in, one product out; an array in, an array out. In the first example, find("TEE-01") is typed Product | undefined and find([…]) is Product[], so neither call needs a check before use.

When one signature with a union parameter would do, prefer it. A generic function with @template is another alternative when the output type follows the input type.

Gotchas

  • Order matters: put the most specific overload first, because TypeScript picks the first one that matches.
  • The implementation must be compatible with every overload; an overload it cannot handle is TS2394 ("This overload signature is not compatible with its implementation signature").

Questions

How do I write function overloads in JSDoc?

With TypeScript 5.0 or later, one /** @overload … */ comment per signature above the function, then the implementation's own comment. Each overload comment has its own @param and @returns.

Sources

Last reviewed 20 October 2026.