Excess properties in a literal
You can order a key from a locksmith by description. If the order lists a tooth that has no notch in the lock, the locksmith will ask again: most likely you made a mistake while dictating the order. But a ready-made key brought from home he only tries in the lock, without asking why it has a key ring.
TypeScript treats objects the same way. Take a function that draws a line from its settings. The color is required, the width may be left out — then it is 1:
interface Options {
color: string;
width?: number;
}
function draw(opts: Options): string {
return `${opts.color} line, ${opts.width ?? 1}px`;
}
console.log(draw({ color: "red", width: 3 })); // red line, 3px
console.log(draw({ color: "blue" })); // blue line, 1pxLet's go through the example line by line:
- In
Options, the propertycoloris required, andwidthis marked with?. drawtakes the width from the settings and, if there is none, puts in1with??.- The first call prints
red line, 3px, the secondblue line, 1px.
Imagine a typo in the word width. In JavaScript the object { color: "red", widht: 3 } passes silently: the function does not find width and draws a line 1 pixel wide. You would have to track the mistake down from a strange picture.
What tsc sees in a literal
An object literal written right where an Options is expected is checked against the type both ways: are all the required properties there, and are there any extra ones. This is the excess property check. Let's try two literals with an extra property:
interface Options {
color: string;
width?: number;
}
const wide: Options = { color: "red", size: 3 }; // ✗
const typo: Options = { color: "red", widht: 3 }; // ✗The messages for the two lines differ.
An unknown property
error TS2353: Object literal may only specify known properties, and 'size' does not exist in type 'Options'.The message says that an object literal may list only known properties, and Options has no size. The type has no property with a similar name, so tsc names the extra one, and that is all.
A similar name
error TS2561: Object literal may only specify known properties, but 'widht' does not exist in type 'Options'. Did you mean to write 'width'?Here the error code is different — TS2561, and at the end tsc asks whether you meant width. It noticed that widht almost matches a real property and suggests the fix. Typos like this are what the check exists for.
A variable gets no such check
The same object with an extra property, stored in a variable first, passes:
interface Options {
color: string;
width?: number;
}
function draw(opts: Options): string {
return `${opts.color} line, ${opts.width ?? 1}px`;
}
const style = { color: "red", width: 3, dashed: true };
console.log(draw(style)); // red line, 3pxstyle has a shape of its own, and it may be useful somewhere else: another function may need dashed, for example. So the usual shape rule applies for draw: the required properties are there, and the extra one does no harm. Like the locksmith with a key from home: the key ring does not bother him.
Only a fresh literal gets the excess property check — an object written right where tsc checks it against a type. Most often that is one of two places:
- right of
=in a declaration with a type:const o: Options = { … }; - a call argument:
draw({ … }).
Why a literal with an extra property fails while the same object from a variable passes is a common interview question.
Common mistake
To get rid of error TS2561, the literal was moved into a variable:
interface Options {
color: string;
width?: number;
}
function draw(opts: Options): string {
return `${opts.color} line, ${opts.width ?? 1}px`;
}
const style = { color: "red", widht: 3 };
console.log(draw(style)); // ✗The compiler stays silent, and the program prints red line, 1px: the typo has not gone anywhere, but tsc no longer sees it. The right fix is the property's name, and if the object must live in a variable, give the type where the object is created: const style: Options = { color: "red", widht: 3 };. Then the literal is fresh again, and tsc shows TS2561 on the right line.
Key points
- A fresh literal — an object written right where it is checked against a type — is checked by tsc for extra properties.
- An extra property is error
TS2353, and one similar to a real property isTS2561with the hint "Did you mean…". - An object from a variable is compared by shape only, and extra properties in it do no harm.
- Moving a literal into a variable to make the error go away hides the typo; give the type where the object is created.