mcpField
T
typescript-best-practices

typescript-best-practices

github.com/ghosttypesDevelopment835 installsUpdated 5w ago
Repository

About typescript-best-practices

A TypeScript development skill for teams seeking consistent, type-safe code. It covers strict configuration, runtime validation, error handling, and import/export conventions, with focused reference files for deeper topics.

Key features

  1. 01Strict TypeScript configuration
  2. 02Explicit public API types
  3. 03Discriminated unions and Result types
  4. 04Runtime type guards and assertions
  5. 05Import and export conventions
  6. 06Topic-specific reference files

Use cases

  1. 01Set up strict tsconfig.json options
  2. 02Model connection states and outcomes
  3. 03Validate unknown data at runtime
  4. 04Organize imports and avoid circular dependencies

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/ghosttypes/ff-5mp-api-ts --skill typescript-best-practices

After installing, type/typescript-best-practicesin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
error-handling.md
generics.md
import-export.md
interfaces-types.md
tsconfig.md
type-guards-assertions.md
unions-discriminated.md
utility-types.md

Details

From the project README

TypeScript Best Practices

Quick Start

Always enable strict mode and use explicit types for public APIs. Prefer type-only imports (import type) and named exports over default exports. Use discriminated unions for state management and type guards for runtime validation.

Type Safety Fundamentals

Strict Mode Configuration

Enable all strict flags in tsconfig.json:

{
  "strict": true,
  "noImplicitAny": true,
  "noImplicitReturns": true,
  "strictNullChecks": true,
  "strictFunctionTypes": true
}
Null Safety
// Explicit null handling
export function findById<T>(items: Map<string, T>, id: string): T | null {
  return items.get(id) ?? null;
}

// Optional chaining and nullish coalescing
export function getName(item?: Item): string {
  return item?.name ?? 'Unknown';
}
Explicit Return Types

Use explicit return types for public APIs:

// Good
export function validateConfig(data: unknown): ValidatedConfig | null {
  const result = ConfigSchema.safeParse(data);
  return result.success ? result.data : null;
}

// Bad - implicit return type
export function validateConfig(data) {
  return data;
}

Core Patterns

Discriminated Unions for State
export type ConnectionState =
  | { status: 'disconnected' }
  | { status: 'connecting'; progress: number }
  | { status: 'connected'; connectionId: string }
  | { status: 'error'; message: string };

// TypeScript knows which properties are available in each branch
Result Type for Error Handling
export type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

const result = await connectToService(options);
if (result.success) {
  console.log('Connected:', result.data.id);
} else {
  console.error('Failed:', result.error.message);
}
Readonly Properties

Use readonly for immutable data:

export interface Config {
  readonly enableFeature: boolean;
  readonly port: number;
}

Type Guards and Assertions

// Type guard
export function isUserData(data: unknown): data is UserData {
  return typeof data === 'object' && data !== null && 'name' in data;
}

// Assertion function
export function assertIsDefined<T>(value: T): asserts value is NonNullable<T> {
  if (value === undefined || value === null) throw new Error('Value is undefined or null');
}

Import/Export Conventions

// Type-only imports (preferred)
import type { Config } from '../types/config';

// Named exports (avoid default exports)
export class DataService {}
export const getService = () => DataService.getInstance();

// Grouped imports
import { External } from 'external';           // External deps
import { internalUtil } from './utils';         // Internal utils
import type { MyType } from './types';          // Types

When to Use References

Reference FileWhen to Load
tsconfig.mdSetting up TypeScript configuration
interfaces-types.mdDefining interfaces, generic types, extending external types
unions-discriminated.mdWorking with discriminated unions, result types, exhaustive checks
type-guards-assertions.mdRuntime validation, branded types, assertion functions
utility-types.mdUsing built-in utilities, const assertions, template literal types
error-handling.mdImplementing structured errors, error factories, retry logic
generics.mdBuilding generic services, repositories, factories, event emitters
import-export.mdOrganizing imports/exports, avoiding circular dependencies

Common Anti-Patterns to Avoid

  1. Using any - Use unknown with type guards instead
  2. Default exports - Harder to refactor and tree-shake
  3. Implicit return types on public APIs
  4. Non-readonly interfaces for immutable data
  5. Nested optionals ({ a?: { b?: string } }) - use discriminated unions instead

Comments

Markdown supported