Get the FREE Ultimate OpenClaw Setup Guide →

typescript-refactorer

npx machina-cli add skill Nembie/claude-code-skills/typescript-refactorer --openclaw
Files (1)
SKILL.md
5.1 KB

TypeScript Refactorer

Before generating any output, read config/defaults.md and adapt all patterns, imports, and code examples to the user's configured stack.

Analysis Process

  1. Scan the specified files for type-related code smells
  2. Categorize issues by severity
  3. Provide corrected code for each issue

Code Smells to Detect

Explicit any Usage

// BAD
function process(data: any) {
  return data.value;
}

// GOOD: Use specific type or generic
function process<T extends { value: unknown }>(data: T) {
  return data.value;
}

// GOOD: Use unknown with type guard
function process(data: unknown) {
  if (isValidData(data)) {
    return data.value;
  }
  throw new Error('Invalid data');
}

Implicit any from Missing Types

// BAD: Parameter implicitly has 'any' type
function calculate(x, y) {
  return x + y;
}

// GOOD
function calculate(x: number, y: number): number {
  return x + y;
}

Unnecessary Type Assertions

// BAD: Assertion when type is already known
const value = getValue() as string; // getValue already returns string

// BAD: Double assertion (type laundering)
const data = response as unknown as User;

// GOOD: Fix the source type or use type guard
const data = isUser(response) ? response : null;

Overly Broad Union Types

// BAD
type Status = string;

// GOOD: Use literal union
type Status = 'pending' | 'active' | 'completed' | 'failed';

// BAD
type Result = { success: boolean; data?: any; error?: string };

// GOOD: Discriminated union
type Result =
  | { success: true; data: User }
  | { success: false; error: string };

Missing Discriminated Unions

// BAD: Ambiguous state
interface State {
  loading: boolean;
  data: User | null;
  error: Error | null;
}

// GOOD: Discriminated union makes invalid states unrepresentable
type State =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: User }
  | { status: 'error'; error: Error };

Implicit Return Types

// BAD: Return type inferred as complex union
function getUser(id: string) {
  if (!id) return null;
  return fetchUser(id); // Returns Promise<User>
}
// Inferred: (id: string) => null | Promise<User>

// GOOD: Explicit return type catches errors
function getUser(id: string): Promise<User | null> {
  if (!id) return Promise.resolve(null);
  return fetchUser(id);
}

Non-null Assertions (!)

// BAD: Hiding potential null issues
const name = user!.name;

// GOOD: Explicit null check
const name = user?.name ?? 'Anonymous';

// GOOD: Early return / throw
if (!user) throw new Error('User required');
const name = user.name;

Type-unsafe Object Access

// BAD
const value = obj['dynamicKey'];

// GOOD: Use Record type
const obj: Record<string, number> = {};
const value = obj['dynamicKey']; // value: number | undefined

// BETTER: Use Map for dynamic keys
const map = new Map<string, number>();
const value = map.get('dynamicKey');

Missing readonly

// BAD: Mutable when shouldn't be
interface Config {
  apiUrl: string;
  timeout: number;
}

// GOOD: Immutable config
interface Config {
  readonly apiUrl: string;
  readonly timeout: number;
}

// Or use Readonly utility
type Config = Readonly<{
  apiUrl: string;
  timeout: number;
}>;

Function Overloads Instead of Unions

// BAD: Unclear relationship between input and output
function parse(input: string | Buffer): string | Uint8Array;

// GOOD: Overloads make it explicit
function parse(input: string): string;
function parse(input: Buffer): Uint8Array;
function parse(input: string | Buffer): string | Uint8Array {
  // Implementation
}

Output Format

## TypeScript Analysis

### Critical (type safety compromised)
- **Explicit any** in `src/utils/api.ts:23`
  - Issue: `data: any` parameter loses all type information
  - Fix: [code block with typed version]

### Warnings (potential issues)
- **Missing discriminated union** in `src/types/state.ts:5`
  - Issue: State type allows invalid combinations
  - Fix: [code block with discriminated union]

### Suggestions (improvements)
- **Implicit return type** in `src/services/user.ts:45`
  - Issue: Complex inferred return type
  - Fix: [code block with explicit return type]

### Summary
- Critical: X issues
- Warnings: X issues
- Suggestions: X issues

Before/After Verification

After suggesting refactoring changes, verify that the refactored code is type-correct by checking for: consistent type usage across the changed files, no introduced type errors in function signatures, all imports still valid. If a suggested refactoring would break a downstream consumer, flag it: BREAKING: this change affects [file/function] — update those references too.

Reference

See references/code-smells.md for a complete catalog of TypeScript anti-patterns.

Source

git clone https://github.com/Nembie/claude-code-skills/blob/main/skills/typescript-refactorer/SKILL.mdView on GitHub

Overview

Analyzes TypeScript code to identify common type-related smells and recommends precise, type-safe refactors. It targets issues like implicit any, missing discriminated unions, overly broad unions, and unnecessary type assertions, then provides corrected code snippets.

How This Skill Works

It scans specified files for type smells, categorizes issues by severity, and outputs corrected code for each issue. It also adapts its patterns to your configured stack by referencing config/defaults.md before generating output.

When to Use It

  • When asked to refactor or tighten types in TS code
  • When cleaning up a codebase to reduce any usage and improve type safety
  • During code reviews to catch implicit any and missing discriminated unions
  • When refactoring to replace type assertions with proper types or guards
  • When introducing readonly and safer dynamic-key data patterns (Record/Map)

Quick Start

  1. Step 1: Run the refactorer on your TS project and review flagged smells
  2. Step 2: Apply the provided corrected code snippets for each issue
  3. Step 3: Run your type checks and tests to verify fixes and regression safety

Best Practices

  • Prefer precise types over any and add guards or generics where needed
  • Use discriminated unions instead of ambiguous state shapes
  • Specify explicit return types to catch errors early
  • Avoid unnecessary type assertions by fixing the source types or using type guards
  • Adopt readonly/Record or Map for dynamic-key data structures

Example Use Cases

  • Refactor a function process(data: any) to a generic T extends { value: unknown } to constrain inputs
  • Convert a function with implicit any parameters to explicit typings like function calculate(x: number, y: number): number
  • Replace a value assertion with a type guard, e.g., if (isUser(response)) return response;
  • Replace type alias Status = string with a literal union Status = 'pending' | 'active' | 'completed' | 'failed'
  • Refactor an interface-based state to a discriminated union with a status field

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers