excess-property-checking

📁 marius-townhouse/effective-typescript-skills 📅 10 days ago
1
总安装量
1
周安装量
#50556
全站排名
安装命令
npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill excess-property-checking

Agent 安装分布

mcpjam 1
openhands 1
replit 1
windsurf 1
zencoder 1

Skill 文档

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;
}

// Excess property checking: Error!
const r: Room = {
  numDoors: 1,
  ceilingHeightFt: 10,
  elephant: 'present',
  // ~~~~~~~ Object literal may only specify known properties,
  //         and 'elephant' does not exist in type 'Room'
};

// Same value via intermediate variable: No error!
const obj = {
  numDoors: 1,
  ceilingHeightFt: 10,
  elephant: 'present',
};
const r2: Room = obj;  // OK - structural typing allows this

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();
  }
}

// Without excess property checking, this typo would be silent:
createWindow({
  title: 'Spider Solitaire',
  darkmode: true  // lowercase 'm' - TYPO!
  // ~~~~~~~ Object literal may only specify known properties,
  //         but 'darkmode' does not exist in type 'Options'.
  //         Did you mean to write 'darkMode'?
});

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; }

// Object literal - checking applies
const p1: Point = { x: 1, y: 2, z: 3 };  // Error: 'z' not in Point

// Variable - checking does NOT apply
const temp = { x: 1, y: 2, z: 3 };
const p2: Point = temp;  // OK

// Type assertion - checking does NOT apply
const p3 = { x: 1, y: 2, z: 3 } as Point;  // OK (but bad practice)

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',  // Error: Did you mean 'logLevel'?
  timeout: 5000,
};

Preventing Wrong Property Names

interface User {
  firstName: string;
  lastName: string;
}

const user: User = {
  first_name: 'John',  // Error: Did you mean 'firstName'?
  last_name: 'Doe',    // Error: Did you mean 'lastName'?
};

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 };  // OK now

Use Intermediate Variable

const options = { title: 'Game', extraProp: true };
createWindow(options);  // OK - excess checking skipped

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 };  // Note: capital 'S'
setOptions(opts);
// ~~~~ Type '{ logScale: boolean; }' has no properties in common
//      with type 'LineChartOptions'

This check applies even through intermediate variables (unlike regular excess property checking).

Common Mistakes

Mistake 1: Expecting Structural Typing to Catch Typos

// ❌ Typo passes silently because no excess property checking
const options = { darkmode: true };  // lowercase 'm'
const config: Options = options;     // No error!

// ✅ Use object literal for catching typos
const config: Options = { darkmode: true };  // Error caught!

Mistake 2: Using Type Assertion to Silence Errors

// ❌ Assertion bypasses the check
const config = { darkmode: true } as Options;

// ✅ Fix the typo instead
const config: Options = { darkMode: true };

Mistake 3: Confusion About Why Error Disappears

// This has an error
const p: Point = { x: 1, y: 2, z: 3 };

// Why doesn't this?
const temp = { x: 1, y: 2, z: 3 };
const p: Point = temp;

// Answer: Excess property checking only applies to object literals!

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.