error TS2561: Object literal may only specify known properties, but 'retires' does not exist in type 'FetchOptions'. Did you mean to write 'retries'? is TS2353 with a suggestion: an object literal written straight into a typed place has a property the type does not declare, and a declared property is close enough in spelling for the checker to name it.
In plain JavaScript the misspelled option is simply ignored at run time, so a retry count, a timeout or a flag quietly keeps its default. In options objects and reducer actions, this is one of the most useful errors checked JavaScript reports.
At a glance
| Code | TS2561 |
|---|---|
| Message | Object literal may only specify known properties, but '{0}' does not exist in type '{1}'. Did you mean to write '{2}'? |
| TypeScript's category | error |
| Listed under | Types do not match |
| Turned on by | No option: every checked file reports it |
| 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}, {1} and {2} are filled in by tsc for each error.
What it looks like
/** @typedef {{ retries?: number, timeoutMs?: number }} FetchOptions */
/** @param {FetchOptions} options */
export function retriesOf(options) {
return options.retries ?? 3;
}
retriesOf({ retires: 5 });error TS2561: Object literal may only specify known properties, but 'retires' does not exist in type 'FetchOptions'. Did you mean to write 'retries'?jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["**/*.js"]
} What causes it
- A typo in an option or property name (
retiresforretries,timoutfortimeout). - A property renamed in the
@typedefbut not at every call site.
How to fix it
Use the name the checker suggests
Editors that run TypeScript's language service offer the rename as a quick fix. Check that the suggestion is the property you meant before accepting it.
/** @typedef {{ retries?: number, timeoutMs?: number }} FetchOptions */
/** @param {FetchOptions} options */
export function retriesOf(options) {
return options.retries ?? 3;
}
retriesOf({ retries: 5 });jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["**/*.js"]
} Or add the property to the type
If the property is real and the type is out of date, add it to the @typedef or the @param type, as for TS2353.
Gotchas
- Like TS2353, the check applies only to object literals written in place. The same object stored in a variable first is not checked for extra properties, so the typo would pass silently.
- With
exactOptionalPropertyTypesor a cast (/** @type {FetchOptions} */ ({ … })), the rules change: a cast skips the excess property check entirely.
Sources
- Object Types: excess property checks · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 21 October 2026.