error TS2353: Object literal may only specify known properties, and 'hostName' does not exist in type ... is reported when you write an object literal straight into a typed place (a typed variable, a parameter, a return value) and one of its properties is not part of the type. The checker treats the extra property as a probable typo.
This check, which the handbook calls excess property checking, only applies to object literals written in place. The same object stored in a variable first and passed later is not checked for extra properties, because other code may legitimately add fields to it.
At a glance
| Code | TS2353 |
|---|---|
| Message | Object literal may only specify known properties, and '{0}' does not exist in type '{1}'. |
| 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} and {1} are filled in by tsc for each error.
What it looks like
/**
* @param {{ port: number, host?: string }} options
*/
export function listen(options) {
return `http://${options.host ?? "localhost"}:${options.port}`;
}
listen({
port: 3000,
hostName: "0.0.0.0",error TS2353: Object literal may only specify known properties, and 'hostName' does not exist in type '{ port: number; host?: string | undefined; }'.
});jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- A property name in an object literal is misspelled or uses another library's name for the option (
hostNameforhost). - The type is out of date: the option exists in the code but not in the
@typedefor@paramtype. - The object deliberately carries extra keys (headers, metadata) and the type does not allow them.
How to fix it
Use the property name the type declares
Most of the time the fix is the spelling. The editor's completion list inside the object literal shows the names the type accepts.
/**
* @param {{ port: number, host?: string }} options
*/
export function listen(options) {
return `http://${options.host ?? "localhost"}:${options.port}`;
}
listen({
port: 3000,
host: "0.0.0.0",
});
/**
* @param {{ port: number, [header: string]: string | number }} headers
*/
export function withHeaders(headers) {
return Object.keys(headers);
}
withHeaders({ port: 3000, "x-request-id": "abc123" });jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Add the property to the type, or allow extra keys
If the property is real, add it to the @typedef or the @param type. If the object is meant to hold any number of named values, give the type an index signature, as the withHeaders function in the fixed example does: { port: number, [header: string]: string | number }.
Gotchas
- Passing a variable instead of a literal skips the check, so
const options = { hostName: "x" }; listen(options)reports the missingportbut not the extrahostName. Writing options inline is the safer habit. - A cast such as
/** @type {Options} */ ({ ... })also skips the excess check, which hides typos the same way.
Questions
Why is an extra property an error at all? JavaScript ignores it.
It is ignored at run time, which is exactly the problem: a misspelled option silently does nothing. Reporting it is the checker's way of catching the typo where it is written.
Sources
- Object Types: Excess Property Checks · TypeScript handbook
- Object Types: Index Signatures · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.