@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
/** @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;jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /**
* @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[]'.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
- TypeScript 5.0: @overload support in JSDoc · TypeScript release notes
- More on Functions: function overloads · TypeScript handbook
Last reviewed 20 October 2026.