Square brackets around the parameter name, @param {string} [label], make it optional: callers may leave it out, and inside the function its type is string | undefined. A default goes inside the brackets for readers, [copies=1], and in the code for the run time, function f(copies = 1).
Typed parameters are required unless marked optional. Calling addLine("TEE-01") when both parameters have @param types is TS2554 ("Expected 2 arguments, but got 1"), as the third example shows. Untyped parameters in a .js file are the exception: TypeScript treats them as optional.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| Optional | /** @param {string} [label] */ | (label?: string) |
| With a default | /** @param {number} [copies=1] */
function f(copies = 1) {} | function f(copies: number = 1) {} |
| Closure spelling | /** @param {boolean=} large */ | (large?: boolean) |
| In a function type | {(sku: string, label?: string) => void} | (sku: string, label?: string) => void |
Examples
/**
* @param {string} sku
* @param {string} [label] shown instead of the SKU when given
* @param {number} [copies=1]
* @param {boolean=} large the Closure spelling of an optional parameter
*/
export function printLabel(sku, label, copies = 1, large) {
const text = label ?? sku;
return Array.from({ length: copies }, () => (large ? text.toUpperCase() : text));
}
printLabel("TEE-01");
printLabel("TEE-01", "Cotton tee", 3);
printLabel("TEE-01", undefined, 2, true);export function printLabel(sku: string, label?: string, copies: number = 1, large?: boolean) {
const text = label ?? sku;
return Array.from({ length: copies }, () => (large ? text.toUpperCase() : text));
}
printLabel("TEE-01");
printLabel("TEE-01", "Cotton tee", 3);
printLabel("TEE-01", undefined, 2, true);jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /**
* @param {string} sku
* @param {string} [label]
*/
export function printLabel(sku, label) {
return `${sku}: ${label.trim()}`;error TS18048: 'label' is possibly 'undefined'.
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /**
* @param {string} sku
* @param {number} quantity
*/
export function addLine(sku, quantity) {
return { sku, quantity };
}
addLine("TEE-01");error TS2554: Expected 2 arguments, but got 1.
addLine("TEE-01", 1);jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} undefined inside the function
An optional parameter without a default may be undefined, so calling a method on it is TS18048 ("'label' is possibly 'undefined'"). Check it, use ?? for a fallback, or give it a default in the code; a default removes undefined from the type.
Three spellings
[label] in the @param tag, {string=} in the type (Closure style) and label?: inside a function type all mean the same thing. Use brackets in @param tags and ?: inside types; the = suffix only works in @param and function types, not on object properties.
Gotchas
- Passing
undefinedexplicitly is allowed for an optional parameter, as the first example does to skiplabel; for a parameter with a default, it makes the default apply.
Questions
How do I document a default value in JSDoc?
Write it in the brackets, @param {number} [copies=1], and also in the function's parameter list. TypeScript uses the one in the code; the one in the comment is for readers and editors.
Sources
- JSDoc Reference: @param · TypeScript handbook
- More on Functions: optional parameters · TypeScript handbook
- Type Checking JavaScript Files: parameters are optional by default · TypeScript handbook
Last reviewed 20 October 2026.