AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Refactoring Typescript

skill-ucdavis-ai-skills-registry-refactoring-typescript · by ucdavis

TypeScript refactoring: SOLID principles, DRY, type safety improvements, and eliminating code smells

No reviews yet
0 installs
45 views
0.0% view→install

Install

$ agentstack add skill-ucdavis-ai-skills-registry-refactoring-typescript

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-ucdavis-ai-skills-registry-refactoring-typescript)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Refactoring Typescript? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Refactoring — TypeScript

Before You Start

  • Ensure existing tests are green. If there are no tests, write them first.
  • Refactor in small, committed steps — one change at a time.
  • Run tsc --noEmit and eslint after each change.
  • Never change behavior while refactoring — if you are, that's a feature.

Type Safety

  • Replace any with proper types or unknown + type guard.
  • Enable strict: true in tsconfig.json if not set.
  • Use interface for object shapes; type for unions and intersections.
  • Prefer readonly arrays and properties when data should not be mutated.
// Before
function process(data: any) { ... }

// After
function process(data: unknown) {
  if (!isOrderData(data)) throw new TypeError('Invalid order data');
  ...
}
// Prefer discriminated unions over boolean flags
type Result =
  | { status: 'ok'; value: string }
  | { status: 'error'; message: string };

Naming

  • Names should say what, not how. Rename when you have to read the body to understand the call site.
  • Boolean variables and functions: prefix with is, has, can, should.
  • Avoid abbreviations except universally understood ones (url, id, ctx).
// Before
const d = users.filter(u => u.a);

// After
const activeUsers = users.filter(user => user.isActive);

SOLID Principles

  • Single Responsibility: if the function name needs "and", split it.
  • Open/Closed: use strategy pattern over if/else chains that grow over time.
  • Liskov Substitution: subtypes must be substitutable without breaking callers.
  • Interface Segregation: split large interfaces; callers should not depend on methods they don't use.
  • Dependency Inversion: accept interfaces, not concrete classes.

Common Smells → Fixes

| Smell | Fix | |-------|-----| | Long parameter list (4+) | Extract to typed options object | | Deep nesting | Early returns / guard clauses | | Magic numbers/strings | Named constants or enums | | Copy-pasted logic | Extract to named function or generic utility | | Large file (300+ lines) | Split into focused modules | | Boolean parameter | Two functions, or discriminated union | | Comments explaining what | Rename so it's self-evident | | Mutable shared state | Encapsulate behind a function; return new values | | Callback pyramid | Async/await with named steps |

Example: Guard Clauses

// Before — deep nesting
function processOrder(order: Order) {
  if (order) {
    if (order.items.length > 0) {
      if (order.status === 'pending') {
        // actual logic...
      }
    }
  }
}

// After — guard clauses
function processOrder(order: Order) {
  if (!order) return;
  if (order.items.length === 0) return;
  if (order.status !== 'pending') return;
  // actual logic...
}

Example: Extract Function

// Before — inline logic that hides intent
const total = items.reduce((sum, item) => {
  const discounted = item.price * (1 - item.discountRate);
  return sum + discounted * item.quantity;
}, 0);

// After — named helpers reveal intent
const lineTotal = (item: Item) => item.price * (1 - item.discountRate) * item.quantity;
const total = items.reduce((sum, item) => sum + lineTotal(item), 0);

Example: Options Object

// Before
function createUser(name: string, age: number, role: string, active: boolean) { ... }

// After
interface CreateUserOptions {
  name: string;
  age: number;
  role: string;
  active: boolean;
}
function createUser(options: CreateUserOptions) { ... }

Example: Async Flattening

// Before — callback pyramid / chained .then
fetchUser(id)
  .then(user => fetchOrders(user.id)
    .then(orders => fetchInvoices(orders[0].id)
      .then(invoices => process(user, orders, invoices))));

// After — sequential async/await
async function loadUserData(id: string) {
  const user = await fetchUser(id);
  const orders = await fetchOrders(user.id);
  const invoices = await fetchInvoices(orders[0].id);
  return process(user, orders, invoices);
}

Example: Strategy Pattern

// Before — growing switch that requires editing this function for each new type
function calculateShipping(method: string, weight: number): number {
  if (method === 'standard') return weight * 0.5;
  if (method === 'express') return weight * 1.2;
  if (method === 'overnight') return weight * 2.5;
  throw new Error('Unknown method');
}

// After — register new strategies without touching existing code
type ShippingStrategy = (weight: number) => number;

const shippingStrategies: Record = {
  standard: w => w * 0.5,
  express:  w => w * 1.2,
  overnight: w => w * 2.5,
};

function calculateShipping(method: string, weight: number): number {
  const strategy = shippingStrategies[method];
  if (!strategy) throw new Error(`Unknown shipping method: ${method}`);
  return strategy(weight);
}

Dead Code

  • Delete unused exports, parameters, branches, and commented-out code — don't leave // removed comments.
  • Use tsc --noEmit and your linter's no-unused-vars / @typescript-eslint/no-unused-vars to surface dead code automatically.

When Not to Refactor

  • Don't refactor code you don't understand yet — read it first.
  • Don't refactor when no tests exist and writing them isn't feasible right now.
  • Don't refactor stable, rarely-touched code just for style — the risk/reward is poor.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.