# TS Clean General

> General Clean Code Principles

- Skill: `caslubbers/ts-clean-general` (Agent Skill)
- Install (CLI): `npx skillmds@latest add caslubbers/ts-clean-general`
- Raw SKILL.md: https://api.skillmd.com/api/skills/caslubbers/ts-clean-general/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: CasLubbers (https://skillmd.com/u/caslubbers)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/caslubbers/ts-clean-general

---


# General Clean Code Principles

## Critical Rules

**G5: DRY (Don't Repeat Yourself)**

Every piece of knowledge has one authoritative representation.

```ts
// Bad - duplication
const taxRate = 0.0825;
const caTotal = subtotal * 1.0825;
const nyTotal = subtotal * 1.07;

// Good - single source of truth
const TAX_RATES: Record<string, number> = { CA: 0.0825, NY: 0.07 };
function calculateTotal(subtotal: number, state: string): number {
  return subtotal * (1 + TAX_RATES[state]);
}
```

**G16: No Obscured Intent**

Don't be clever. Be clear.

```ts
// Bad - what does this do?
return ((x & 0x0f) << 4) | (y & 0x0f);

// Good - obvious intent
return packCoordinates(x, y);
```

**G23: Prefer Polymorphism to If/Else**

```ts
// Bad - will grow forever
function calculatePay(employee: {
  type: "SALARIED" | "HOURLY" | "COMMISSIONED";
  salary?: number;
  hours?: number;
  rate?: number;
  base?: number;
  commission?: number;
}): number {
  if (employee.type === "SALARIED") {
    return employee.salary ?? 0;
  } else if (employee.type === "HOURLY") {
    return (employee.hours ?? 0) * (employee.rate ?? 0);
  } else if (employee.type === "COMMISSIONED") {
    return (employee.base ?? 0) + (employee.commission ?? 0);
  }
  return 0;
}

// Good - open/closed principle
interface Employee {
  calculatePay(): number;
}

class SalariedEmployee implements Employee {
  constructor(private readonly salary: number) {}
  calculatePay(): number {
    return this.salary;
  }
}

class HourlyEmployee implements Employee {
  constructor(
    private readonly hours: number,
    private readonly rate: number,
  ) {}
  calculatePay(): number {
    return this.hours * this.rate;
  }
}

class CommissionedEmployee implements Employee {
  constructor(
    private readonly base: number,
    private readonly commission: number,
  ) {}
  calculatePay(): number {
    return this.base + this.commission;
  }
}
```

**G25: Replace Magic Numbers with Named Constants**

```ts
// Bad
if (elapsedTime > 86400) {
  // ...
}

// Good
const SECONDS_PER_DAY = 86400;
if (elapsedTime > SECONDS_PER_DAY) {
  // ...
}
```

**G30: Functions Should Do One Thing**

If you can extract another function, your function does more than one thing.

**G36: Law of Demeter (Avoid Train Wrecks)**

```ts
// Bad - reaching through multiple objects
const outputDir = context.options.scratchDir.absolutePath;

// Good - one dot
const outputDir = context.getScratchDir();
```

**Composition Over Inheritance**

Inheritance couples a subclass to its parent's internals forever. Use it only for a genuine
is-a relationship where the subclass is substitutable everywhere the parent is. For reuse, compose.

```typescript
// Bad - extends to borrow one method, inherits the entire surface
class EmailNotifier extends SmtpClient {
  notify(user: User, message: string) {
    this.send(user.email, message)
  }
}

// Good - holds what it needs
class EmailNotifier {
  constructor(private readonly smtp: SmtpClient) {}

  notify(user: User, message: string) {
    this.smtp.send(user.email, message)
  }
}
```

The composed version takes a fake `SmtpClient` in tests, can swap transports, and exposes only
`notify`. The extended version makes every `SmtpClient` method part of its own public API.

Signals you extended for the wrong reason: an override that throws, an override ignoring parameters
the base requires, or a three-deep hierarchy with the real behaviour in the middle.

TypeScript makes the alternatives cheap. Use an `interface` for the contract, and union types where
subclasses were only ever acting as an enum:

```typescript
// Bad - a class hierarchy standing in for three shapes
abstract class Shape { abstract area(): number }

// Good - discriminated union, exhaustively checkable
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number }

function area(shape: Shape): number {
  switch (shape.kind) {
    case "circle": return Math.PI * shape.radius ** 2
    case "square": return shape.side ** 2
  }
}
```

In React the same rule reads: compose components and extract hooks. There is no component
inheritance worth having.

## Enforcement Checklist

When reviewing AI-generated code, verify:
- [ ] No duplication (G5)
- [ ] Clear intent, no magic numbers (G16, G25)
- [ ] Polymorphism over conditionals (G23)
- [ ] Functions do one thing (G30)
- [ ] No Law of Demeter violations (G36)
- [ ] Boundary conditions handled (G3)
- [ ] Dead code removed (G9)
- [ ] Composition preferred over inheritance
- [ ] Module reads top-down, callers above callees

