SKILL.md raw


name: typescript description: This skill should be used when working with TypeScript code, including type definitions, type inference, generics, utility types, and TypeScript configuration. Provides comprehensive knowledge of TypeScript patterns, best practices, and advanced type system features.


TypeScript Skill

This skill provides comprehensive knowledge and patterns for working with TypeScript effectively in modern applications.

When to Use This Skill

Use this skill when:

Core Concepts

Type System Fundamentals

TypeScript provides static typing for JavaScript with a powerful type system that includes:

Type Inference

Leverage TypeScript's type inference to write less verbose code:

Type Safety Patterns

Implement type-safe patterns:

Key Workflows

1. Designing Type-Safe APIs

When designing APIs, follow these patterns:

Interface vs Type Alias:

Generic Constraints:

// Use extends for generic constraints
function getValue<T extends { id: string }>(item: T): string {
  return item.id
}

Discriminated Unions:

// Use for type-safe state machines
type State =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: Data }
  | { status: 'error'; error: Error }

2. Working with Utility Types

Use built-in utility types for common transformations:

3. Advanced Type Patterns

Mapped Types:

// Transform object types
type Nullable<T> = {
  [K in keyof T]: T[K] | null
}

type ReadonlyDeep<T> = {
  readonly [K in keyof T]: T[K] extends object
    ? ReadonlyDeep<T[K]>
    : T[K]
}

Conditional Types:

// Type-level logic
type IsArray<T> = T extends Array<any> ? true : false

type Flatten<T> = T extends Array<infer U> ? U : T

Template Literal Types:

// String manipulation at type level
type EventName<T extends string> = `on${Capitalize<T>}`
type Route = `/api/${'users' | 'posts'}/${string}`

4. Type Narrowing

Use type guards and narrowing techniques:

typeof guards:

if (typeof value === 'string') {
  // value is string here
}

instanceof guards:

if (error instanceof Error) {
  // error is Error here
}

Custom type guards:

function isUser(value: unknown): value is User {
  return typeof value === 'object' && value !== null && 'id' in value
}

Discriminated unions:

function handle(state: State) {
  switch (state.status) {
    case 'idle':
      // state is { status: 'idle' }
      break
    case 'success':
      // state is { status: 'success'; data: Data }
      console.log(state.data)
      break
  }
}

5. Working with External Libraries

Typing Third-Party Libraries:

Declaration Files:

// globals.d.ts
declare global {
  interface Window {
    myCustomProperty: string
  }
}

export {}

6. TypeScript Configuration

Configure tsconfig.json for strict type checking:

Essential Strict Options:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "skipLibCheck": true
  }
}

Best Practices

1. Prefer Type Inference Over Explicit Types

Let TypeScript infer types when they're obvious from context.

2. Use Strict Mode

Enable strict type checking to catch more errors at compile time.

3. Avoid any Type

Use unknown for truly unknown types, then narrow with type guards.

4. Use Const Assertions

Use as const for immutable values and narrow literal types.

5. Leverage Discriminated Unions

Use for state machines and variant types for better type safety.

6. Create Reusable Generic Types

Extract common type patterns into reusable generics.

7. Use Branded Types for Nominal Typing

Create distinct types for values with same structure but different meaning.

8. Document Complex Types

Add JSDoc comments to explain non-obvious type decisions.

9. Use Type-Only Imports

Use import type for type-only imports to aid tree-shaking.

10. Handle Errors with Type Guards

Use type guards to safely work with error objects.

Common Patterns

React Component Props

// Use interface for component props
interface ButtonProps {
  variant?: 'primary' | 'secondary'
  size?: 'sm' | 'md' | 'lg'
  onClick?: () => void
  children: React.ReactNode
}

export function Button({ variant = 'primary', size = 'md', onClick, children }: ButtonProps) {
  // implementation
}

API Response Types

// Use discriminated unions for API responses
type ApiResponse<T> =
  | { success: true; data: T }
  | { success: false; error: string }

// Helper for safe API calls
async function fetchData<T>(url: string): Promise<ApiResponse<T>> {
  try {
    const response = await fetch(url)
    const data = await response.json()
    return { success: true, data }
  } catch (error) {
    return { success: false, error: String(error) }
  }
}

Store/State Types

// Use interfaces for state objects
interface AppState {
  user: User | null
  isAuthenticated: boolean
  theme: 'light' | 'dark'
}

// Use type for actions (discriminated union)
type AppAction =
  | { type: 'LOGIN'; payload: User }
  | { type: 'LOGOUT' }
  | { type: 'SET_THEME'; payload: 'light' | 'dark' }

References

For detailed information on specific topics, refer to:

Troubleshooting

Common Type Errors

Type 'X' is not assignable to type 'Y':

Object is possibly 'null' or 'undefined':

Type 'any' implicitly has...

Cannot find module or its type declarations:

Integration with Project Stack

React 19

Use TypeScript with React 19 features:

TanStack Ecosystem

Type TanStack libraries properly:

Zod Integration

Combine Zod with TypeScript:

Resources

The TypeScript documentation provides comprehensive information: