Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Ts Clean General

ASecurity

Use when writing, fixing, editing, or reviewing TypeScript code quality. Enforces Clean Code's core principles—DRY, single responsibility, clear intent, no magic numbers, proper abstractions. Also trigger on: duplicated logic across files or branches (G5), magic numbers or hardcoded strings (G25), long if/else chains that should be union types plus polymorphism (G23), chained property access like `a.b.c.d` or long optional-chain trains (G36), functions juggling multiple responsibilities (G30)...

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmenttypescriptgoreactapi

Works with

cliapi

Security Analysis

A100/100

Scanned 9/19/2026

$npx -y skills add CasLubbers/code-design-skills --skill ts-clean-general --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ts Clean General?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Ts Clean General
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/caslubbers-ts-clean-general/badge)](https://www.skillsdirectory.com/skills/caslubbers-ts-clean-general)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: ts-clean-general
description: Use when writing, fixing, editing, or reviewing TypeScript code quality. Enforces Clean Code's core principles—DRY, single responsibility, clear intent, no magic numbers, proper abstractions. Also trigger on: duplicated logic across files or branches (G5), magic numbers or hardcoded strings (G25), long if/else chains that should be union types plus polymorphism (G23), chained property access like `a.b.c.d` or long optional-chain trains (G36), functions juggling multiple responsibilities (G30), clever one-liners whose intent is not obvious (G16). Also trigger on: a class extending another to reuse one method, an override that throws, a hierarchy three levels deep, an abstract class standing in for a union type, or asks like "should this extend or compose", "composition over inheritance".
---

# 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

Attribution

CasLubbersCasLubbers
View sourceSee grades on GitHubMore from CasLubbers →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10341 votes
View all in development →