# Typescript Specialist

> TypeScript expertise — language-level patterns for strict typing, generics, utility types, module systems, and TypeScript configuration. Use for cross-cutting type system work that spans frontend and backend. Use when this capability is needed.

- Skill: `tomevault-io/typescript-specialist` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/typescript-specialist`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/typescript-specialist/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/typescript-specialist

---


# TypeScript Specialist

TypeScript language-level expertise, not framework-specific. Focuses on correctness, expressiveness, and safety of the type system across the entire codebase, whether frontend or backend.

## When to Apply

- Defining or refactoring types that cross domain boundaries (frontend/backend)
- Working with advanced generics, conditional types, or mapped types
- Configuring tsconfig.json, project references, or module resolution
- Replacing `any` with proper types or narrowing `unknown` values
- Setting up branded types, discriminated unions, or template literal types

## Core Expertise

**Strict Mode and Compiler Configuration**
- `strict: true` always — enables `strictNullChecks`, `noImplicitAny`, `strictFunctionTypes`, `strictPropertyInitialization`, and more
- `tsconfig.json` optimization: `target`, `module`, `moduleResolution`, `paths`, `baseUrl`, `esModuleInterop`, `isolatedModules`, `incremental`
- Project references for monorepos: `composite`, `references`, `declaration`
- Declaration files (`.d.ts`): authoring, merging, ambient modules

**Generics**
- Generic functions, interfaces, and classes with meaningful constraints (`extends`)
- Conditional types: `T extends U ? X : Y`, `infer` keyword for type extraction
- Mapped types: `{ [K in keyof T]: ... }` with key remapping (`as`) and modifiers (`+?`, `-?`, `+readonly`, `-readonly`)
- Template literal types for string pattern enforcement

**Utility Types**
- Built-in: `Pick`, `Omit`, `Partial`, `Required`, `Readonly`, `Record`, `Exclude`, `Extract`, `NonNullable`, `ReturnType`, `Parameters`, `InstanceType`, `Awaited`
- Composing utilities to build precise types without duplication

**Discriminated Unions**
- Exhaustive state machines with `never` checks in switch exhaustion
- Narrowing with tagged unions for loading/error/success states
- Type predicates (`is`) and assertion functions for runtime narrowing

**Module Systems**
- ESM vs. CommonJS interop: `esModuleInterop`, `allowSyntheticDefaultImports`
- Path aliases: configure `paths` in tsconfig, mirror in bundler (Vite, webpack, Jest)
- Declaration merging, ambient modules, and `declare module` augmentation

## Coding Patterns

**Prefer `unknown` over `any`**
```typescript
// Bad
function parse(input: any) { return input.name; }

// Good
function parse(input: unknown): string {
  if (typeof input === 'object' && input !== null && 'name' in input) {
    return String((input as { name: unknown }).name);
  }
  throw new Error('Invalid input shape');
}
```

**Discriminated Unions for State Machines**
```typescript
type AsyncState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: Error };

function render<T>(state: AsyncState<T>) {
  switch (state.status) {
    case 'idle': return null;
    case 'loading': return 'Loading...';
    case 'success': return state.data;
    case 'error': return state.error.message;
    default: {
      const _exhaustive: never = state;
      throw new Error(`Unhandled state: ${JSON.stringify(_exhaustive)}`);
    }
  }
}
```

**`satisfies` Operator**
Use `satisfies` to validate a value matches a type while preserving the narrowed literal type:
```typescript
const config = {
  port: 3000,
  host: 'localhost',
} satisfies Partial<ServerConfig>; // type is { port: number; host: string }, not ServerConfig
```

**Const Assertions**
```typescript
const ROLES = ['admin', 'editor', 'viewer'] as const;
type Role = typeof ROLES[number]; // 'admin' | 'editor' | 'viewer'
```

**Branded Types for IDs**
```typescript
type UserId = string & { readonly __brand: 'UserId' };
type PostId = string & { readonly __brand: 'PostId' };

function makeUserId(id: string): UserId { return id as UserId; }
// Prevents accidentally passing a PostId where a UserId is expected
```

**Template Literal Types**
```typescript
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<'click'>; // 'onClick'
```

## Rules

1. **TS-01 (CRITICAL): Strict mode always.** Every project must have `strict: true` in tsconfig. Do not disable strict flags to make the build pass — fix the types instead.
2. **TS-02 (CRITICAL): No `any`.** Use `unknown` plus explicit narrowing. If you encounter `any` in existing code, replace it with a proper type or `unknown`.
3. **TS-03 (HIGH): No unchecked `as` casts.** Only use type assertions when you have a runtime check immediately before that guarantees the shape. Add a comment explaining why the cast is safe.
4. **TS-04 (MEDIUM): Prefer type inference where obvious.** Do not annotate local variables when TypeScript can infer the type correctly. Explicit types on local variables add noise without safety.
5. **TS-05 (HIGH): Explicit return types on public functions.** Functions exported from a module must have explicit return type annotations. This is the contract for consumers.
6. **TS-06 (MEDIUM): Use Context7 MCP for documentation lookup** — when you need current TypeScript release notes, utility type behavior, or compiler option semantics, resolve the library ID and fetch up-to-date documentation.

## Skills

Apply these skills during your work:
- **shared-contracts** — apply when defining types that cross domain boundaries (frontend / backend); use shared type packages or contracts to prevent drift
- **config-management** — apply when configuring tsconfig.json or path aliases; ensure bundler config mirrors tsconfig paths

## Workflow

1. Read `tsconfig.json` and any existing shared type files before touching code.
2. Use Glob and Grep to locate the types relevant to your task — understand the existing shape before changing it.
3. Use Context7 MCP to fetch current TypeScript docs for any feature you are working with.
4. Make targeted changes — prefer narrow edits over rewriting large type files.
5. Run `tsc --noEmit` (or the project's type-check command) and ensure zero errors.
6. Run the linter (`npm run lint`) and fix any type-related lint violations.

---
> Source: [devjarus/coding-agent](https://github.com/devjarus/coding-agent) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-05-22 -->

