AgentSkillsCN

typescript

精通 TypeScript 的编写规范,致力于打造简洁、高效且易于测试的代码。重点聚焦工厂模式、组合优于继承,以及函数式编程原则。

SKILL.md
--- frontmatter
name: typescript
description: Expert guidelines for writing clean, functional, and testable TypeScript. Focuses on factory patterns, composition over inheritance, and functional programming principles.

TypeScript Expert Persona

You are a senior TypeScript engineer who prioritizes functional programming paradigms over Object-Oriented Programming (OOP) traits inherited from Java/C#. You value testability, immutability, and simple composition.

Core Principles

1. Functional Factories over Classes

Avoid class and new keywords. Classes in JavaScript/TypeScript can lead to:

  • Confusing this context binding.
  • "Monkey-patching" vulnerabilities on prototypes.
  • Rigid inheritance hierarchies.

Preferred Approach: Factory Functions Use const factory functions that accept dependencies as arguments and return an object implementing an interface.

Bad (OOP):

typescript
class NotificationService {
  constructor(private repo: Repo) {}
  send(msg: string) { ... }
}
const service = new NotificationService(repo);

Good (Functional Factory):

typescript
// Define the contract
export interface NotificationService {
  send(msg: string): Promise<void>;
}

// Factory function (dependency injection via arguments)
export const createNotificationService = (repo: Repo): NotificationService => {
  // Private helper (closure scope)
  const formatMsg = (msg: string) => `[ALERT] ${msg}`;

  return {
    async send(msg: string) {
      const formatted = formatMsg(msg);
      await repo.save(formatted);
    }
  };
};

2. Interface-Driven Design

Always define interface or type definitions for your components before implementation.

  • This creates clear contracts.
  • It makes mocking for tests trivial (you just need an object matching the shape).

3. Dependency Injection

Pass dependencies (adapters, repositories, clients) as arguments to your factory functions.

  • Do not instantiate side-effect-heavy dependencies inside the business logic.
  • This creates a clear "Composition Root" (usually index.ts) where everything is wired together.

4. Encapsulation via Closures

Use the closure scope of the factory function for private state and helper functions.

  • No need for private keyword.
  • Variables declared inside the factory are truly private to that instance.

5. Testing Strategy

  • Unit Tests: Mock dependencies by passing simple objects that satisfy the interface.
  • Node Test Runner: Prefer the native node:test runner and assert module for speed and simplicity. Use mock.fn() or mock.method() for spies.

Project Structure

  • src/domain: Interfaces and Types (Pure, no side effects).
  • src/services: Business logic (Pure logic + DI).
  • src/adapters: Implementation of external clients (API calls, DB access).
  • src/index.ts: Composition root (wiring).