Claude
Skills
Sign in
Back

typescript-helper

Included with Lifetime
$97 forever

TypeScript development guidance for type systems and tooling When user works with .ts or .tsx files, mentions TypeScript, or encounters type errors

General

What this skill does


# TypeScript Helper Agent

## What's New in TypeScript 5.7 & 2025

- **Never-Initialized Variables**: Detects variables that are never assigned in nested scopes
- **Path Rewriting**: `--rewriteRelativeImportExtensions` auto-converts .ts → .js imports
- **ES2024 Support**: `Object.groupBy()`, `Map.groupBy()`, `Promise.withResolvers()`
- **V8 Compile Caching**: `module.enableCompileCache()` = ~2.5x faster startup (Node 22+)
- **TypeScript 7.0 Preview**: 10x speedup, multi-threaded builds coming soon
- **Direct Execution**: ts-node, tsx, and Node 23.x `--experimental-strip-types`

## Overview

This agent helps you work with TypeScript for type-safe development, including type system usage, configuration, error resolution, and tooling integration.

## CLI Commands

### TypeScript Compiler

```bash
# Compile TypeScript files
tsc

# Watch mode
tsc --watch

# Compile specific file
tsc app.ts

# Check types without emitting
tsc --noEmit

# Show compiler version
tsc --version

# Initialize tsconfig.json
tsc --init
```

### Type Checking

```bash
# Type check entire project
tsc --noEmit

# Type check with specific config
tsc --project tsconfig.build.json --noEmit

# Type check single file
tsc --noEmit file.ts
```

### Running TypeScript

```bash
# Using ts-node
ts-node app.ts

# Using tsx (faster, recommended)
tsx app.ts

# Using bun (fastest for most workloads)
bun run app.ts

# Node.js 23+ with experimental type stripping (no transpilation!)
node --experimental-strip-types app.ts

# With V8 compile caching for 2.5x faster startup (Node 22+)
node --experimental-strip-types --enable-source-maps app.ts
```

### Modern TypeScript 5.7+ Features

**Path rewriting for imports**:

```typescript
// tsconfig.json
{
  "compilerOptions": {
    "rewriteRelativeImportExtensions": true
  }
}

// You write:
import { foo } from "./utils.ts";

// TypeScript rewrites to:
import { foo } from "./utils.js";

// Enables direct .ts imports that work in Node.js ESM
```

**ES2024 features now available**:

```typescript
// Object.groupBy()
const people = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "Charlie", age: 30 },
];

const byAge = Object.groupBy(people, (person) => person.age);
// { 25: [{name: "Bob", ...}], 30: [{name: "Alice", ...}, {name: "Charlie", ...}] }

// Map.groupBy()
const grouped = Map.groupBy(people, (person) => person.age);
// Map { 25 => [{...}], 30 => [{...}, {...}] }

// Promise.withResolvers()
const { promise, resolve, reject } = Promise.withResolvers<number>();
setTimeout(() => resolve(42), 1000);
await promise; // 42
```

**V8 compile caching (Node 22+)**:

```typescript
// Enable at app entry point for ~2.5x faster startup
import { enableCompileCache } from "node:module";

enableCompileCache();

// All subsequent module loads use V8's code cache
```

## Common TypeScript Patterns

### Type Annotations

```typescript
// Basic types
let name: string = "Alice";
let age: number = 30;
let active: boolean = true;
let items: string[] = ["a", "b", "c"];
let tuple: [string, number] = ["hello", 42];

// Objects
interface User {
  id: number;
  name: string;
  email?: string; // Optional property
  readonly createdAt: Date; // Readonly
}

const user: User = {
  id: 1,
  name: "Alice",
  createdAt: new Date(),
};

// Functions
function greet(name: string): string {
  return `Hello, ${name}`;
}

const add = (a: number, b: number): number => a + b;

// Async functions
async function fetchData(): Promise<User> {
  const response = await fetch("/api/user");
  return response.json();
}
```

### Interfaces vs Types

```typescript
// Interface
interface Point {
  x: number;
  y: number;
}

// Type alias
type Point2D = {
  x: number;
  y: number;
};

// Type alias for union
type Status = "pending" | "approved" | "rejected";

// Extending interface
interface Point3D extends Point {
  z: number;
}

// Intersection type
type ColoredPoint = Point & {
  color: string;
};
```

### Generics

```typescript
// Generic function
function identity<T>(value: T): T {
  return value;
}

// Generic interface
interface Container<T> {
  value: T;
  getValue(): T;
}

// Generic with constraints
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// Generic with default
interface Response<T = unknown> {
  data: T;
  status: number;
}
```

### Utility Types

```typescript
// Partial - all properties optional
type PartialUser = Partial<User>;

// Required - all properties required
type RequiredUser = Required<User>;

// Pick - select specific properties
type UserBasic = Pick<User, "id" | "name">;

// Omit - exclude specific properties
type UserWithoutEmail = Omit<User, "email">;

// Record - create object type
type UserRoles = Record<string, string>;

// Exclude/Extract
type Status = "pending" | "approved" | "rejected";
type ApprovedStatus = Extract<Status, "approved">;
type NotPending = Exclude<Status, "pending">;

// ReturnType
type AddResult = ReturnType<typeof add>; // number

// Parameters
type AddParams = Parameters<typeof add>; // [number, number]
```

### Advanced Patterns

```typescript
// Discriminated unions
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "rectangle"; width: number; height: number };

function area(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "rectangle":
      return shape.width * shape.height;
  }
}

// Branded types
type UserId = string & { readonly __brand: "UserId" };
type Email = string & { readonly __brand: "Email" };

function createUserId(id: string): UserId {
  return id as UserId;
}

// Type guards
function isString(value: unknown): value is string {
  return typeof value === "string";
}

// Assertion functions
function assertString(value: unknown): asserts value is string {
  if (typeof value !== "string") {
    throw new Error("Not a string");
  }
}
```

## tsconfig.json Configuration

### Basic Configuration

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020", "DOM"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
```

### Strict Mode Options

```json
{
  "compilerOptions": {
    "strict": true, // Enables all below
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true
  }
}
```

### Additional Checks

```json
{
  "compilerOptions": {
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true
  }
}
```

## Common Type Errors and Fixes

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

```typescript
// Problem
let num: number = "5"; // Error

// Fix: Correct the type
let num: number = 5;

// Or parse if from string
let num: number = parseInt("5");
```

### Error: Object is possibly 'null' or 'undefined'

```typescript
// Problem
function greet(name: string | null) {
  return name.toUpperCase(); // Error
}

// Fix 1: Type guard
function greet(name: string | null) {
  if (name === null) return "";
  return name.toUpperCase();
}

// Fix 2: Non-null assertion (use cautiously)
function greet(name: string | null) {
  return name!.toUpperCase();
}

// Fix 3: Optional chaining
function greet(name: string | null) {
  return name?.toUpperCase() ?? "";
}
```

### Error: Property 'X' does not exist on type 'Y'

```typescript
// Problem
const obj: { name: string } = { name: "Alice", age: 30 }; // Error

// Fix: Add property to type
interface Person {
  name: string;

Related in General