🎯

record-types-sync

🎯Skill

from marius-townhouse/effective-typescript-skills

VibeIndex|
What it does

Synchronizes and validates properties across data structures using TypeScript record types, ensuring comprehensive updates and type safety.

πŸ“¦

Part of

marius-townhouse/effective-typescript-skills(83 items)

record-types-sync

Installation

Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills --all
Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills -s prefer-unknown-over-any exhaustiveness-checking
Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills -a opencode claude-code
Quick InstallInstall with npx
npx skills add marius-townhouse/effective-typescript-skills -l
git cloneClone repository
git clone https://github.com/marius-townhouse/effective-typescript-skills.git
πŸ“– Extracted from docs: marius-townhouse/effective-typescript-skills
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Use when properties need synchronized configuration. Use when adding new properties requires updates elsewhere. Use when implementing optimization checks. Use when building property validators. Use when maintaining parallel data structures.

Overview

# Use Record Types to Keep Values in Sync

Overview

When you have parallel data structures that need to stay synchronized - like a type and a configuration object for that type's properties - use Record to enforce that every property is accounted for. This technique ensures that when you add a new property to a type, you get a compile error reminding you to update related code.

This pattern is invaluable for optimization checks, property validators, and any code that needs to enumerate or configure all properties of a type.

When to Use This Skill

  • Properties need synchronized configuration
  • Adding new properties requires updates elsewhere
  • Implementing shouldComponentUpdate-style optimizations
  • Building property validators or transformers
  • Maintaining parallel data structures

The Iron Rule

Use Record to enforce that all properties of T are accounted for in related configuration objects.

Detection

Watch for these maintenance hazards:

```typescript

// RED FLAGS - Manual synchronization

interface Props {

data: Data;

onClick: () => void;

}

function shouldUpdate(old: Props, new: Props) {

// Manual checks - easy to miss new properties

return old.data !== new.data; // Forgot onClick!

}

// Comments that won't be read:

// Note: if you add a property here, update shouldUpdate!

```

The Problem

```typescript

interface ScatterProps {

xs: number[];

ys: number[];

xRange: [number, number];

yRange: [number, number];

color: string;

onClick?: () => void;

}

// "Fail open" - might redraw too often

function shouldUpdate(old: ScatterProps, new: ScatterProps) {

for (const k in old) {

if (old[k] !== new[k]) {

if (k !== 'onClick') return true; // Forgot new event handlers!

}

}

return false;

}

// "Fail closed" - might miss necessary redraws

function shouldUpdate(old: ScatterProps, new: ScatterProps) {

return (

old.xs !== new.xs ||

old.ys !== new.ys ||

// Forgot xRange, yRange, color!

// Also forgot to exclude onClick

);

}

```

The Solution: Record Types

```typescript

const REQUIRES_UPDATE: Record = {

xs: true,

ys: true,

xRange: true,

yRange: true,

color: true,

onClick: false, // false = change doesn't require redraw

};

function shouldUpdate(old: ScatterProps, new: ScatterProps) {

for (const k in old) {

const key = k as keyof ScatterProps;

if (old[key] !== new[key] && REQUIRES_UPDATE[key]) {

return true;

}

}

return false;

}

```

Now adding a new property forces you to decide:

```typescript

interface ScatterProps {

// ... existing properties

onDoubleClick?: () => void; // New property added

}

// COMPILE ERROR: Property 'onDoubleClick' is missing

const REQUIRES_UPDATE: Record = {

// ... existing entries

// Error reminds you to add: onDoubleClick: ???

};

```

Property Validators

```typescript

interface UserInput {

name: string;

email: string;

age: number;

}

// Enforce that every field has a validator

const validators: Record boolean> = {

name: (v) => typeof v === 'string' && v.length > 0,

email: (v) => typeof v === 'string' && v.includes('@'),

age: (v) => typeof v === 'number' && v >= 0 && v < 150,

};

// Adding a field forces adding a validator

```

Default Values

```typescript

interface Config {

timeout: number;

retries: number;

debug: boolean;

}

// Enforce defaults for all properties

const defaults: Record = {

timeout: 5000,

retries: 3,

debug: false,

};

function loadConfig(partial: Partial): Config {

return { ...defaults, ...partial };

}

```

Property Labels

```typescript

interface FormData {

firstName: string;

lastName: string;

email: string;

}

// Enforce labels for all fields

const labels: Record = {

firstName: 'First Name',

lastName: 'Last Name',

email: 'Email Address',

};

// Use in UI

Object.entries(formData).map(([key, value]) => (

));

```

Pressure Resistance Protocol

When maintaining parallel structures:

  1. Identify coupling: Which structures must stay synchronized?
  2. Use Record: Enforce complete coverage
  3. Choose meaningful value types: boolean, function, string, etc.
  4. Document the pattern: Explain why Record is used
  5. Handle optional properties: Use keyof Required if needed

Red Flags

| Anti-Pattern | Problem | Solution |

|--------------|---------|----------|

| Comments saying "update X when Y changes" | Won't be enforced | Record type |

| Manual property enumeration | Easy to miss properties | Record with keyof |

| Optional config entries | Might forget required ones | Make all required |

Common Rationalizations

"I'll remember to update it"

Reality: You won't. Your coworkers won't. The compiler will enforce it with Record types.

"It's just a small config"

Reality: Small configs grow. Record types scale with zero maintenance burden.

"Some properties don't need configuration"

Reality: Explicitly setting them to null/false/empty is better than forgetting them.

Quick Reference

| Use Case | Record Type | Example Value |

|----------|-------------|---------------|

| Optimization flags | Record | true/false |

| Validators | Record | validation function |

| Defaults | Record | default value |

| Labels | Record | display name |

| Transformers | Record | transform function |

The Bottom Line

Use Record to enforce that parallel data structures stay synchronized with your types. The compiler will remind you to update related code when you add new properties.

Reference

  • Effective TypeScript, 2nd Edition by Dan Vanderkam
  • Item 61: Use Record Types to Keep Values in Sync

More from this repository10

🎯
tsdoc-comments🎯Skill

Generates TypeScript documentation comments (TSDoc) to explain public APIs, complex types, and provide comprehensive code documentation with IDE tooltips.

🎯
async-over-callbacks🎯Skill

Transforms callback-based asynchronous code into clean, readable async/await patterns for better type flow and error handling.

🎯
type-safe-monkey-patching🎯Skill

Enables type-safe runtime extension of global objects and DOM elements in TypeScript without sacrificing type checking or using `as any`.

🎯
create-objects-all-at-once🎯Skill

Efficiently initializes multiple TypeScript objects simultaneously using concise object literal syntax and spread operators.

🎯
module-by-module-migration🎯Skill

Guides developers through systematic TypeScript module migration, breaking down complex refactoring into manageable, incremental steps.

🎯
ts-js-relationship🎯Skill

Explains TypeScript's relationship to JavaScript, highlighting how it adds static typing and catches errors before runtime while remaining fully compatible with JavaScript code.

🎯
code-gen-independent🎯Skill

Generates JavaScript code despite TypeScript type errors and demonstrates that TypeScript types are erased at runtime, requiring alternative type checking strategies.

🎯
context-type-inference🎯Skill

Helps restore precise type context when extracting values, preventing type inference errors through annotations, const assertions, and type preservation techniques.

🎯
precise-string-types🎯Skill

Enforces strict string type constraints and prevents unintended string type conversions in TypeScript projects.

🎯
type-display-attention🎯Skill

Displays and simplifies complex TypeScript types to improve IDE readability and developer experience.