Claude Code Plugins

Community-maintained marketplace

Feedback

TypeScript Conventions

@majiayu000/claude-skill-registry
27
0

|

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name typescript-conventions
description Apply TypeScript conventions when writing or refactoring TypeScript code to ensure type safety and consistency. Not for JavaScript or other languages.
user-invocable false

TypeScript Team Conventions

TypeScript conventions that auto-apply when writing TypeScript code. These conventions ensure consistency, type safety, and maintainability across the codebase.

Type Strictness

Always enforce:

  • Use strict mode: "strict": true in tsconfig.json
  • Never use any (use unknown instead)
  • Define explicit return types for all functions
  • Prefer interfaces over types for object shapes

Example - Good:

interface UserRepository {
  findById(id: UserId): Promise<Result<User, NotFoundError>>;
  save(user: User): Promise<Result<void, DatabaseError>>;
}

function validateEmail(email: string): Result<Email, ValidationError> {
  // implementation
}

Example - Bad:

function validateEmail(email: any): any {
  // DON'T use 'any'
}

Error Handling

Requirements:

  • Never throw bare errors; use typed error classes
  • Always include context: new ValidationError('message', { context })
  • Use Result pattern for operations that can fail
  • Handle async errors with try/catch in async functions

Example - Good:

class ValidationError extends Error {
  constructor(
    message: string,
    public readonly field?: string,
    public readonly context?: Record<string, unknown>,
  ) {
    super(message);
    this.name = "ValidationError";
  }
}

function validateUser(
  user: unknown,
): Result<UserValidationResult, ValidationError> {
  try {
    // validation logic
    return { success: true, data: result };
  } catch (error) {
    return {
      success: false,
      error: new ValidationError("Validation failed", "user", {
        error: error.message,
      }),
    };
  }
}

Example - Bad:

function validateUser(user: any) {
  if (!user) throw new Error("Invalid user"); // DON'T use bare Error
  return user;
}

Naming Conventions

Follow these patterns:

Type Convention Example
Interfaces PascalCase with descriptive names UserRepository, MarketData
Types PascalCase UserId, ApiResponse<T>
Enums PascalCase UserRole, HttpStatus
Variables/functions camelCase getUserById, userData
Constants UPPER_SNAKE_CASE MAX_RETRIES, DEFAULT_TIMEOUT

Examples:

interface UserRepository {} // ✅ Good
type UserId = string; // ✅ Good
enum UserRole {} // ✅ Good
const MAX_RETRIES = 3; // ✅ Good
function getUserById(id: UserId) {} // ✅ Good

Module Organization

File structure:

  • Use: src/<domain>/<feature>/<File.ts>
  • Export only public interfaces from index.ts
  • Keep files under 300 lines
  • Use named exports, avoid default exports

Example - Good:

// src/user/UserRepository.ts
export interface UserRepository {
  findById(id: UserId): Promise<Result<User, NotFoundError>>;
}

export class DatabaseUserRepository implements UserRepository {
  async findById(id: UserId): Promise<Result<User, NotFoundError>> {
    // implementation
  }
}

Immutability Pattern (CRITICAL)

WHY: Prevents stale closures, makes state predictable, enables React optimizations.

✅ ALWAYS use spread operator:

const updatedUser = { ...user, name: "New Name" };
const updatedArray = [...items, newItem];

❌ NEVER mutate directly:

user.name = "New Name"; // BAD - causes bugs
items.push(newItem); // BAD - breaks React optimizations

Code Organization

Best practices:

  • Group related functionality into classes or modules
  • Use dependency injection for services
  • Keep pure functions separate from side-effect code
  • Prefer composition over inheritance
  • Use early returns over deep nesting

Example - Good:

function processUser(user: User): Result<ProcessedUser, ValidationError> {
  if (!user) {
    return { success: false, error: new ValidationError("User required") };
  }

  if (!isValidEmail(user.email)) {
    return { success: false, error: new ValidationError("Invalid email") };
  }

  return { success: true, data: process(user) };
}

Testing Standards

Requirements:

  • Write tests for all public functions
  • Use descriptive test names: should_return_user_when_id_exists
  • Mock external dependencies
  • Aim for 80%+ code coverage

Example - Good:

describe("UserRepository", () => {
  describe("findById", () => {
    it("should return user when id exists", async () => {
      const repo = new DatabaseUserRepository(mockDb);
      const result = await repo.findById("user-123");
      expect(result.success).toBe(true);
      expect(result.data).toEqual(expectedUser);
    });

    it("should return error when user not found", async () => {
      const repo = new DatabaseUserRepository(mockDb);
      const result = await repo.findById("non-existent");
      expect(result.success).toBe(false);
    });
  });
});

Type Safety Over Convenience

WHY: Types catch bugs at compile-time, serve as documentation, enable refactoring.

✅ GOOD (proper types):

interface Market {
  id: string;
  name: string;
  status: "active" | "resolved" | "closed";
}

function getMarket(id: string): Promise<Market> {}

❌ BAD (using any):

function getMarket(id: any): Promise<any> {}

Constants Over Magic Numbers

Use named constants instead of magic numbers:

✅ Good:

const MIN_AGE = 18;
const MAX_AGE = 120;
const MIN_NAME_LENGTH = 2;
const MAX_NAME_LENGTH = 100;

if (user.age < MIN_AGE || user.age > MAX_AGE) {
  throw new ValidationError("Age out of range");
}

❌ Bad:

if (user.age < 18 || user.age > 120) {
  // Magic numbers
  throw new Error("Invalid age");
}

Performance Best Practices

Use for:

  • Expensive computations (useMemo)
  • Functions passed to children (useCallback)
  • Pure components (React.memo)
const sortedMarkets = useMemo(() => {
  return markets.sort((a, b) => b.volume - a.volume);
}, [markets]);

const handleSearch = useCallback((query: string) => {
  setSearchQuery(query);
}, []);

Common Anti-Patterns to Avoid

Using any for types

// DON'T
function process(data: any): any {}

Default exports

// DON'T
export default function process() {}

Bare throw new Error()

// DON'T
throw new Error("Something went wrong");

Mixed concerns in single file

// DON'T - mixing business logic, UI, and data access
function UserComponent() {
  // UI logic
  // Data access
  // Business logic
}

Magic numbers without constants

// DON'T
if (retries > 3) {
}

Console.log in production

// DON'T
console.log("User data:", user);

Verification Checklist

Before considering TypeScript code complete:

  • Strict mode enabled in tsconfig.json
  • No any types (use unknown instead)
  • Explicit return types defined
  • Typed error classes used (not bare Error)
  • Result pattern for operations that can fail
  • Immutability pattern followed (spread operators)
  • Constants instead of magic numbers
  • Descriptive naming conventions
  • Files under 300 lines
  • Named exports (no default)
  • Tests written for all public functions
  • 80%+ code coverage

Integration

This skill integrates with:

  • coding-standards - Universal coding best practices
  • engineering-lifecycle - Testing requirements
  • frontend-patterns - React/TypeScript patterns
  • backend-patterns - TypeScript backend patterns

Dynamic Sourcing Protocol

**CONDITIONAL FETCH**: For TypeScript language questions, fetch from:

This skill contains Seed System-specific conventions (Result pattern, immutability, naming conventions) that extend TypeScript fundamentals.


Genetic Code

This component carries essential Seed System principles for context: fork isolation:

MANDATORY: All components MUST be self-contained (zero .claude/rules dependency) MANDATORY: Achieve 80-95% autonomy (0-5 AskUserQuestion rounds per session) MANDATORY: Description MUST use What-When-Not format in third person MANDATORY: No component references another component by name in description MANDATORY: Progressive disclosure - references/ for detailed content MANDATORY: Use XML for control (mission_control, critical_constraint), Markdown for data No exceptions. Portability invariant must be maintained.

Delta Standard: Good Component = Expert Knowledge − What Claude Already Knows

Recognition Questions:

  • "Would Claude know this without being told?" → Delete (zero delta)
  • "Can this work standalone?" → Fix if no (non-self-sufficient)
  • "Did I read the actual file, or just see it in grep?" → Verify before claiming MANDATORY: Define explicit return types for all functions MANDATORY: Use Result pattern for operations that can fail MANDATORY: Use typed error classes, never bare Error MANDATORY: Never mutate objects directly (use spread operator) No exceptions. Type safety prevents runtime bugs.