An object type lists the properties a value must have, each with its type: {{ street: string, city: string, unit?: string }}. The outer braces belong to the JSDoc tag and the inner ones to the type, which is why object types in JSDoc start with {{.
A ? after the name makes a property optional. Commas and semicolons both separate properties; TypeScript prints semicolons in its messages.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| Inline | /** @param {{ street: string, city: string }} address */ | (address: { street: string; city: string }) |
| Optional property | {{ unit?: string }} | { unit?: string } |
| Named | /** @typedef {{ street: string, city: string }} Address */ | type Address = { street: string; city: string }; |
Examples
/**
* @param {{ street: string, city: string, unit?: string }} address
* @param {{ express: boolean; giftWrap?: boolean }} [options]
*/
export function shippingLabel(address, options) {
const speed = options?.express ? "EXPRESS" : "STANDARD";
return [address.unit, address.street, address.city, speed].filter(Boolean).join("\n");
}
shippingLabel({ street: "12 Market St", city: "Springfield" });
shippingLabel({ street: "12 Market St", city: "Springfield", unit: "4B" }, { express: true });export function shippingLabel(
address: { street: string; city: string; unit?: string },
options?: { express: boolean; giftWrap?: boolean },
) {
const speed = options?.express ? "EXPRESS" : "STANDARD";
return [address.unit, address.street, address.city, speed].filter(Boolean).join("\n");
}
shippingLabel({ street: "12 Market St", city: "Springfield" });
shippingLabel({ street: "12 Market St", city: "Springfield", unit: "4B" }, { express: true });jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /** @param {{ street: string, city: string, unit?: string }} address */
export function shippingLabel(address) {
return `${address.street}, ${address.city}`;
}
shippingLabel({ street: "12 Market St", city: "Springfield", unti: "4B" });error TS2353: Object literal may only specify known properties, and 'unti' does not exist in type '{ street: string; city: string; unit?: string | undefined; }'.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} /** @type {{ street: string, unit: string= }} */error TS1247: A type literal property cannot have an initializer.error TS1109: Expression expected.
const address = { street: "12 Market St" };error TS2741: Property 'unit' is missing in type '{ street: string; }' but required in type '{ street: string; unit: string; }'.
export { address };jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Misspelled properties
When you pass an object literal straight to a parameter, TypeScript rejects properties the type does not have. unti: "4B" instead of unit is TS2353 ("Object literal may only specify known properties"), as the second example shows. The check applies to fresh literals only; an object stored in a variable first may carry extra properties.
The postfix = is not optional
Older JSDoc marks an optional property with = after its type: unit: string=. TypeScript does not support that form inside object types. TypeScript 5.9 reports a syntax error in the comment (TS1247 and TS1109) and then treats the property as required (TS2741 on the object), as the third example shows. Write unit?: string.
Inline or named?
Inline shapes are fine for one-off parameters. As soon as a shape appears twice, or is longer than one line, give it a name with @typedef; the name shows in hovers and error messages instead of the whole shape.
Gotchas
- Methods can be written as properties with function types,
{{ save: (draft: string) => void }}, or in method form,{{ save(draft: string): void }}. - With
exactOptionalPropertyTypes, an optional property cannot be set toundefinedexplicitly; without it,unit: undefinedis allowed.
Questions
How do I write an object type in JSDoc?
Inside the tag's braces, write the type's own braces with the properties: @param {{ id: string, tags?: string[] }} item.
Sources
- Object Types · TypeScript handbook
- JSDoc Reference: unsupported patterns · TypeScript handbook
Last reviewed 20 October 2026.