error TS7031: Binding element 'name' implicitly has an 'any' type. is the destructuring form of TS7006: a parameter written as { name, email } (or [first, second]) has no type, so every name pulled out of it is reported once.
JSDoc has no place to put a type next to each name, so the tag describes the whole object. The tag's name is yours to pick, because the parameter itself has none.
At a glance
| Code | TS7031 |
|---|---|
| Message | Binding element '{0}' implicitly has an '{1}' type. |
| TypeScript's category | error |
| Listed under | Implicit any |
| Turned on by | noImplicitAny, strict |
| In .js files | Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file |
The message is TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} and {1} are filled in by tsc for each error.
What it looks like
export function userCard({ name, email }) {error TS7031: Binding element 'name' implicitly has an 'any' type.error TS7031: Binding element 'email' implicitly has an 'any' type.
return `${name} <${email}>`;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- A parameter is a destructuring pattern and there is no
@paramtag for it, no default value with a type, and no context (a typed callback) to supply one. noImplicitAnyis on (part ofstrict).
How to fix it
Describe the object in one @param tag
@param {{ name: string, email: string }} user types both names. For a longer list, the nested form reads better: @param {object} options followed by @param {string} options.name and @param {boolean} [options.compact], with brackets for optional ones. A @typedef works too, when other functions take the same object.
/**
* @param {{ name: string, email: string }} user
*/
export function userCard({ name, email }) {
return `${name} <${email}>`;
}
/**
* @param {object} options
* @param {string} options.name
* @param {boolean} [options.compact]
*/
export function badge({ name, compact = false }) {
return compact ? name.slice(0, 1) : name;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Gotchas
- A default in the pattern (
compact = false) types that one name, but the others still need the tag. - The names in nested
@paramtags must match the destructured names. A misspelled one (options.nam) describes a property the pattern does not read, so the destructurednameis reported as TS2339.
Sources
- JSDoc Reference: @param and @returns · TypeScript handbook
- More on Functions: Parameter Destructuring · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.