TypeScript Development

SkillDev tools

Write TypeScript code following best practices. Use when developing TypeScript/JavaScript applications. Covers type safety, patterns, and tooling.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the TypeScript Development skill

What this skill tells your AI

The instructions your AI receives, as published by nguyenhuuca/assessment in .claude/skills/languages/typescript/SKILL.md and read by ahel’s review.

Project Setup

# Initialize with pnpm
pnpm init
pnpm add -D typescript @types/node

# TypeScript config
npx tsc --init

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"]
}

Type Patterns

Discriminated Unions

type Result<T> =
  | { success: true; data: T }
  | { success: false; error: Error };

function handleResult(result: Result<User>) {
  if (result.success) {
    console.log(result.data); // User
  } else {
    console.error(result.error); // Error
  }
}

Branded Types

type UserId = string & { readonly brand: unique symbol };
type OrderId = string & { readonly brand: unique symbol };

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

Utility Types

// Make all properties optional
Partial<User>

// Make all properties required
Required<User>

// Pick specific properties
Pick<User, 'id' | 'email'>

// Omit specific properties
Omit<User, 'password'>

// Make properties readonly
Readonly<User>

Error Handling

// Result type pattern
type Result<T, E = Error> =
  | { ok: true; value: T }
  | { ok: false; error: E };

async function fetchUser(id: string): Promise<Result<User>> {
  try {
    const user = await db.users.findById(id);
    if (!user) {
      return { ok: false, error: new Error('User not found') };
    }
    return { ok: true, value: user };
  } catch (error) {
    return { ok: false, error: error as Error };
  }
}

Testing with Vitest

import { describe, test, expect, vi } from 'vitest';

describe('UserService', () => {
  test('creates user with valid email', async () => {
    const service = new UserService(mockRepo);
    const user = await service.create('test@example.com');
    expect(user.email).toBe('test@example.com');
  });

  test('throws on invalid email', async () => {
    const service = new UserService(mockRepo);
    await expect(service.create('invalid')).rejects.toThrow();
  });
});

Tooling

# Biome (linting + formatting)
pnpm add -D @biomejs/biome
pnpm biome check --apply .

# Vitest (testing)
pnpm add -D vitest
pnpm vitest

Signals

GitHub stars
34
Forks
25
Last commit
Sep 2026
Hacker News mentions
20
Advanced
Catalog kind
skill
Gateway key
typescript-nguyenhuuca
Source
github.com/nguyenhuuca/assessment