| name | excess-property-checking |
| description | Use when assigning object literals to typed variables. Use when confused by "unknown property" errors. Use when extra properties are flagged on object literals but not variables. |
Distinguish Excess Property Checking from Type Checking
Overview
Object literals get special treatment: TypeScript flags unknown properties.
This catches typos and mistakes that structural typing would miss. But it only applies to object literals - understanding this distinction prevents confusion.
When to Use This Skill
- Assigning object literals to typed variables
- Confused why extra properties cause errors sometimes
- Error disappears when using intermediate variable
- Working with optional properties where typos are likely
- Designing interfaces with many optional fields
The Iron Rule
ALWAYS remember: Excess property checking only applies to OBJECT LITERALS.
Remember:
- Object literal → extra properties flagged
- Variable assignment → structural typing applies
- Type assertions → bypass excess property checking
Detection: The "Extra Property" Error
When you see "Object literal may only specify known properties", you've triggered excess property checking.
interface Room {
numDoors: number;
ceilingHeightFt: number;
}
const r: Room = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: 'present',
};
const obj = {
numDoors: 1,
ceilingHeightFt: 10,
elephant: 'present',
};
const r2: Room = obj;
Why Excess Property Checking Exists
Structural typing is powerful but permissive. It allows extra properties, which can hide bugs:
interface Options {
title: string;
darkMode?: boolean;
}
function createWindow(options: Options) {
if (options.darkMode) {
setDarkMode();
}
}
createWindow({
title: 'Spider Solitaire',
darkmode: true
});
When Excess Property Checking Applies
| Context | Excess Property Checking? |
|---|
| Object literal assigned to typed variable | Yes |
| Object literal as function argument | Yes |
| Object literal as return value | Yes |
| Variable assigned to typed variable | No |
| Type assertion | No |
interface Point { x: number; y: number; }
const p1: Point = { x: 1, y: 2, z: 3 };
const temp = { x: 1, y: 2, z: 3 };
const p2: Point = temp;
const p3 = { x: 1, y: 2, z: 3 } as Point;
When Excess Property Checking Helps
Catching Typos in Optional Properties
interface Config {
logLevel?: 'debug' | 'info' | 'warn' | 'error';
timeout?: number;
retries?: number;
}
const config: Config = {
loglevel: 'debug',
timeout: 5000,
};
Preventing Wrong Property Names
interface User {
firstName: string;
lastName: string;
}
const user: User = {
first_name: 'John',
last_name: 'Doe',
};
Bypassing Excess Property Checking (When Intentional)
Use Index Signature for Known Extra Properties
interface Options {
darkMode?: boolean;
[otherOptions: string]: unknown;
}
const o: Options = { darkmode: true };
Use Intermediate Variable
const options = { title: 'Game', extraProp: true };
createWindow(options);
Weak Types: A Related Check
"Weak" types have only optional properties. TypeScript adds a special check:
interface LineChartOptions {
logscale?: boolean;
invertedYAxis?: boolean;
areaChart?: boolean;
}
const opts = { logScale: true };
setOptions(opts);
This check applies even through intermediate variables (unlike regular excess property checking).
Common Mistakes
Mistake 1: Expecting Structural Typing to Catch Typos
const options = { darkmode: true };
const config: Options = options;
const config: Options = { darkmode: true };
Mistake 2: Using Type Assertion to Silence Errors
const config = { darkmode: true } as Options;
const config: Options = { darkMode: true };
Mistake 3: Confusion About Why Error Disappears
const p: Point = { x: 1, y: 2, z: 3 };
const temp = { x: 1, y: 2, z: 3 };
const p: Point = temp;
Pressure Resistance Protocol
1. "Just Add as Type"
Pressure: "The type assertion makes the error go away"
Response: Assertions bypass safety checks. Fix the actual issue.
Action: Correct the property name or update the type definition.
2. "TypeScript Is Being Too Strict"
Pressure: "Extra properties shouldn't matter"
Response: This catches real bugs like typos in optional fields.
Action: If you truly need extra properties, use an index signature.
3. "It Works With a Variable"
Pressure: "Just use an intermediate variable to avoid the error"
Response: That hides bugs. The error exists for a reason.
Action: Investigate why the extra property exists.
Red Flags - STOP and Reconsider
- Using type assertion to silence excess property errors
- Creating intermediate variables just to avoid checks
- Confused why some assignments error and others don't
- Thinking TypeScript is inconsistent about extra properties
Common Rationalizations (All Invalid)
| Excuse | Reality |
|---|
| "It's just an extra property" | Extra properties often indicate typos |
| "Structural typing allows this" | Object literals have stricter rules for good reason |
| "The assertion fixes it" | Assertions hide bugs, they don't fix them |
Quick Reference
| Scenario | Excess Property Check? | Example |
|---|
| Object literal to typed var | Yes | const x: T = { ... } |
| Object literal as argument | Yes | fn({ ... }) |
| Variable to typed var | No | const temp = {...}; const x: T = temp; |
| Type assertion | No | { ... } as T |
| Weak type (via variable) | Checks for common props | Special case |
The Bottom Line
Excess property checking catches bugs that structural typing would miss.
It only applies to object literals, not variables. This is intentional - it catches typos in property names, especially for optional properties. Don't bypass it with assertions or intermediate variables; instead, fix the underlying issue.
Reference
Based on "Effective TypeScript" by Dan Vanderkam, Item 11: Distinguish Excess Property Checking from Type Checking.