typescript-best-practices
Guide AI agents through TypeScript coding best practices including type safety, error handling, code organization, and architecture patterns. This skill should be used when generating TypeScript code, reviewing TypeScript files, creating new TypeScript modules, refactoring JavaScript to TypeScript, or when the user asks about TypeScript patterns, types, or coding standards. Keywords: typescript, types, coding standards, best practices, type safety, generics, architecture, refactoring.
What this skill does
# TypeScript Best Practices
Guide AI agents in writing high-quality TypeScript code. This skill provides coding standards, architecture patterns, and tools for analysis and scaffolding.
## When to Use This Skill
Use this skill when:
- Generating new TypeScript code
- Reviewing TypeScript files for quality issues
- Creating new modules, services, or components
- Refactoring JavaScript to TypeScript
- Answering questions about TypeScript patterns or types
- Designing APIs or interfaces
Do NOT use this skill when:
- Working with pure JavaScript (no TypeScript)
- Debugging runtime errors (use debugging tools)
- Framework-specific patterns (React, Vue, etc. - use framework skills)
## Core Principles
### 1. Type Safety First
Maximize compile-time error detection:
```typescript
// Prefer unknown over any for unknown types
function processInput(data: unknown): string {
if (typeof data === "string") return data;
if (typeof data === "number") return String(data);
throw new Error("Unsupported type");
}
// Explicit return types for public APIs
export function calculateTotal(items: ReadonlyArray<Item>): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
// Use const assertions for literal types
const CONFIG = {
mode: "production",
version: 1,
} as const;
```
### 2. Immutability by Default
Prevent accidental mutations:
```typescript
// Use readonly for object properties
interface User {
readonly id: string;
readonly email: string;
name: string; // Only mutable if intentional
}
// Use ReadonlyArray for collections
function processItems(items: ReadonlyArray<Item>): ReadonlyArray<Result> {
return items.map(transform);
}
// Prefer spreading over mutation
function updateUser(user: User, name: string): User {
return { ...user, name };
}
```
### 3. Error Handling with Types
Use the type system for error handling:
```typescript
// Result type for recoverable errors
type Result<T, E = Error> =
| { success: true; value: T }
| { success: false; error: E };
// Typed error classes
class ValidationError extends Error {
constructor(
message: string,
readonly field: string,
readonly code: string
) {
super(message);
this.name = "ValidationError";
}
}
// Function with Result return type
function parseConfig(input: string): Result<Config, ValidationError> {
try {
const data = JSON.parse(input);
if (!isValidConfig(data)) {
return {
success: false,
error: new ValidationError("Invalid config", "root", "INVALID_FORMAT"),
};
}
return { success: true, value: data };
} catch {
return {
success: false,
error: new ValidationError("Parse failed", "root", "PARSE_ERROR"),
};
}
}
```
### 4. Code Organization
Structure code for maintainability:
```typescript
// One concept per file
// user.ts - User type and related utilities
export interface User {
readonly id: string;
readonly email: string;
readonly createdAt: Date;
}
export function createUser(email: string): User {
return {
id: crypto.randomUUID(),
email,
createdAt: new Date(),
};
}
// Explicit exports (no barrel file wildcards)
// index.ts
export { User, createUser } from "./user.ts";
export { validateEmail } from "./validation.ts";
```
## Quick Reference
| Category | Prefer | Avoid |
|----------|--------|-------|
| Unknown types | `unknown` | `any` |
| Collections | `ReadonlyArray<T>` | `T[]` for inputs |
| Objects | `Readonly<T>` | Mutable by default |
| Null checks | Optional chaining `?.` | `!= null` |
| Type narrowing | Type guards | `as` assertions |
| Return types | Explicit on exports | Inferred on exports |
| Enums | String literal unions | Numeric enums |
| Imports | Named imports | Default imports |
| Errors | Result types | Throwing for flow control |
| Loops | `for...of`, `.map()` | `for...in` on arrays |
## Code Generation Guidelines
When generating TypeScript code, follow these patterns:
### Module Structure
```typescript
/**
* Module description
* @module module-name
*/
// === Types ===
export interface ModuleOptions {
readonly setting: string;
}
export interface ModuleResult {
readonly data: unknown;
}
// === Constants ===
const DEFAULT_OPTIONS: ModuleOptions = {
setting: "default",
};
// === Implementation ===
export function processData(
input: unknown,
options: Partial<ModuleOptions> = {}
): ModuleResult {
const opts = { ...DEFAULT_OPTIONS, ...options };
// Implementation
return { data: input };
}
```
### Function Design
```typescript
// Pure functions preferred
function transform(input: Input): Output {
// No side effects, same input = same output
return { ...input, processed: true };
}
// Explicit parameter types
function fetchUser(id: string, options?: FetchOptions): Promise<User> {
// Implementation
}
// Use function overloads for complex signatures
function parse(input: string): ParsedData;
function parse(input: Buffer): ParsedData;
function parse(input: string | Buffer): ParsedData {
// Implementation
}
```
### Interface Design
```typescript
// Prefer interfaces for object shapes
interface UserData {
readonly id: string;
readonly email: string;
}
// Use type for unions and intersections
type UserRole = "admin" | "user" | "guest";
type AdminUser = UserData & { readonly role: "admin" };
// Document with JSDoc
/**
* Configuration for the API client
* @property baseUrl - The base URL for API requests
* @property timeout - Request timeout in milliseconds
*/
interface ApiConfig {
readonly baseUrl: string;
readonly timeout?: number;
}
```
## Common Anti-Patterns
Avoid these patterns when generating code:
| Anti-Pattern | Problem | Solution |
|--------------|---------|----------|
| `any` type | Disables type checking | Use `unknown` and narrow |
| `as` assertions | Runtime errors | Use type guards |
| Non-null `!` | Null pointer errors | Optional chaining `?.` |
| Mutable params | Unexpected mutations | `Readonly<T>` |
| Magic strings | Typos, no autocomplete | String literal types |
| God classes | Hard to test/maintain | Single responsibility |
| Circular deps | Build/runtime issues | Dependency inversion |
| Index signatures | Lose type info | Explicit properties |
See `references/anti-patterns/common-mistakes.md` for detailed examples.
## Scripts Reference
### analyze.ts
Analyze TypeScript code for quality issues:
```bash
deno run --allow-read scripts/analyze.ts <path> [options]
Options:
--strict Enable all checks
--json Output JSON for programmatic use
--fix-hints Show suggested fixes
Examples:
# Analyze a file
deno run --allow-read scripts/analyze.ts ./src/utils.ts
# Analyze directory with strict mode
deno run --allow-read scripts/analyze.ts ./src --strict
# JSON output for CI
deno run --allow-read scripts/analyze.ts ./src --json
```
### generate-types.ts
Generate TypeScript types from JSON data:
```bash
deno run --allow-read --allow-write scripts/generate-types.ts <input> [options]
Options:
--name <name> Root type name (default: inferred)
--output <path> Output file path
--readonly Generate readonly types
--interface Use interface instead of type
Examples:
# Generate from JSON file
deno run --allow-read scripts/generate-types.ts ./data.json --name Config
# Generate readonly interface
deno run --allow-read --allow-write scripts/generate-types.ts ./api-response.json \
--interface --readonly --output ./types/api.ts
```
### scaffold-module.ts
Create properly structured TypeScript modules:
```bash
deno run --allow-read --allow-write scripts/scaffold-module.ts [options]
Options:
--name <name> Module name (required)
--path <path> Target directory (default: ./src)
--type <type> Type: service, util, component
--with-tests Include test file
Examples:
# Create a utility module
deno run --allow-read --allow-write scripts/scaffold-module.ts \
--name "string-utils" --type uRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.