Brackets with an equals sign give a type parameter a default: @template [T=string]. When a type is used without type arguments, Field instead of Field<number>, or a class is created with nothing to infer from, the default is used. TypeScript 4.5 added defaults to JSDoc.
Defaults are most useful on generic @typedefs and classes, where they keep the common case short.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| A default | /** @template [T=string] */ | <T = string> |
| Constraint and default | /** @template {string | number} [T=number] */ | <T extends string | number = number> |
Examples
/**
* @template [T=string]
* @typedef {{ value: T, error?: string }} Field
*/
/** @type {Field} */
const name = { value: "Jane" };
/** @type {Field<number>} */
const age = { value: 34 };
name.value.toUpperCase();
age.value.toFixed(0);
export { name, age };type Field<T = string> = { value: T; error?: string };
const name: Field = { value: "Jane" };
const age: Field<number> = { value: 34 };
name.value.toUpperCase();
age.value.toFixed(0);
export { name, age };jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /** @template [T=string] */
export class Store {
/** @type {T[]} */
items = [];
/** @param {T} item */
add(item) {
this.items.push(item);
}
}
const notes = new Store();
notes.add("Restock mugs");
notes.add(42);error TS2345: 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"]
} /** @template [K=string], V @typedef {{ key: K, value: V }} Pair */error TS2706: Required type parameters may not follow optional type parameters.
/** @type {Pair<string, number>} */
const pair = { key: "TEE-01", value: 12 };
export { pair };jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} On classes
new Store() in the second example has no argument that mentions T, so the default applies and notes is a Store<string>; adding a number is TS2345. Without the default, T would be any in a .js file and nothing would be checked.
Defaults come last
Parameters with defaults must come after the ones without. @template [K=string], V is TS2706 ("Required type parameters may not follow optional type parameters"), as the third example shows.
Gotchas
- Defaults do not affect inference when there is an argument to infer from:
new Store([1, 2])with a constructor parameter of typeT[]would infernumber. - Before TypeScript 4.5, a JSDoc type parameter could not have a default.
Questions
How do I give a JSDoc type parameter a default?
Put the name in brackets with the default after an equals sign: @template [T=unknown]. It works since TypeScript 4.5.
Sources
- TypeScript 4.5: const assertions and default type arguments in JSDoc · TypeScript release notes
- Generics: generic parameter defaults · TypeScript handbook
Last reviewed 20 October 2026.