MCPInstall

javascript-typescript

Modern JavaScript and TypeScript development patterns

Installs
83
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/miles990/claude-software-skills --skill javascript-typescript
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads javascript-typescript automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

JavaScript & TypeScript

Overview

Modern JavaScript (ES6+) and TypeScript patterns for building robust applications.


TypeScript Fundamentals

Type Definitions

// Basic types
type UserId = string;
type Timestamp = number;

// Object types
interface User {
  id: UserId;
  email: string;
  name: string;
  createdAt: Timestamp;
  metadata?: Record<string, unknown>;
}

// Union types
type Status = 'pending' | 'active' | 'inactive';

// Discriminated unions
type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

// Generic types
interface Repository<T extends { id: string }> {
  find(id: string): Promise<T | null>;
  findAll(filter?: Partial<T>): Promise<T[]>;
  create(data: Omit<T, 'id'>): Promise<T>;
  update(id: string, data: Partial<T>): Promise<T>;
  delete(id: string): Promise<void>;
}

// Utility types
type CreateUserInput = Omit<User, 'id' | 'createdAt'>;
type UpdateUserInput = Partial<Pick<User, 'name' | 'metadata'>>;
type UserKeys = keyof User;

// Conditional types
type Nullable<T> = T | null;
type NonNullableFields<T> = {
  [K in keyof T]-?: NonNullable<T[K]>;
};

// Template literal types
type EventName = `on${Capitalize<string>}`;
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiRoute = `/${string}`;

Type Guards

// Type predicates
function isUser(obj: unknown): obj is User {
  return (
    typeof obj === 'object' &&
    obj !== null &&
    'id' in obj &&
    'email' in obj &&
    typeof (obj as User).id === 'string'
  );
}

// Discriminated union guards
interface Dog {
  kind: 'dog';
  bark(): void;
}

interface Cat {
  kind: 'cat';
  meow(): void;
}

type Animal = Dog | Cat;

function handleAnimal(animal: Animal) {
  switch (animal.kind) {
    case 'dog':
      animal.bark(); // TypeScript knows this is Dog
      break;
    case 'cat':
      animal.meow(); // TypeScript knows this is Cat
      break;
  }
}

// Assertion functions
function assertIsString(value: unknown): asserts value is string {
  if (typeof value !== 'string') {
    throw new Error('Value must be a string');
  }
}

// Exhaustive checks
function assertNever(x: never): never {
  throw new Error(`Unexpected value: ${x}`);
}

Async Patterns

Promises and Async/Await

// Promise creation
function delay(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// Async/await with error handling
async function fetchUser(id: string): Promise<Result<User>> {
  try {
    const response = await fetch(`/api/users/${id}`);

    if (!response.ok) {
      return {
        success: false,
        error: new Error(`HTTP ${response.status}`),
      };
    }

    const data = await response.json();
    return { success: true, data };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error : new Error(String(error)),
    };
  }
}

// Parallel execution
async function fetchAllUsers(ids: string[]): Promise<User[]> {
  const results = await Promise.all(ids.map((id) => fetchUser(id)));

  return results
    .filter((r): r is { success: true; data: User } => r.success)
    .map((r) => r.data);
}

// Promise.allSettled for partial failures
async function fetchUsersSettled(ids: string[]) {
  const results = await Promise.allSettled(
    ids.map((id) => fetch(`/api/users/${id}`).then((r) => r.json()))
  );

  return results.map((result, index) => ({
    id: ids[index],
    status: result.status,
    value: result.status === 'fulfilled' ? result.value : null,
    error: result.status === 'rejected' ? result.reason : null,
  }));
}

// Sequential execution with reduce
async function processSequentially<T, R>(
  items: T[],
  processor: (item: T) => Promise<R>
): Promise<R[]> {
  return items.reduce(async (accPromise, item) => {
    const acc = await accPromise;
    const result = await processor(item);
    return [...acc, result];
  }, Promise.resolve([] as R[]));
}

Async Iterators

// Async generator
async function* paginate<T>(
  fetcher: (page: number) => Promise<{ data: T[]; hasMore: boolean }>
): AsyncGenerator<T[], void, unknown> {
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const result = await fetcher(page);
    yield result.data;
    hasMore = result.hasMore;
    page++;
  }
}

// Using async iterator
async function getAllItems() {
  const items: Item[] = [];

  for await (const batch of paginate(fetchPage)) {
    items.push(...batch);
  }

  return items;
}

// Async iterator utilities
async function* map<T, R>(
  iterable: AsyncIterable<T>,
  fn: (item: T) => R | Promise<R>
): AsyncGenerator<R> {
  for await (const item of iterable) {
    yield await fn(item);
  }
}

async function* filter<T>(
  iterable: AsyncIterable<T>,
  predicate: (item: T) => boolean | Promise<boolean>
): AsyncGenerator<T> {
  for await (const item of iterable) {
    if (await predicate(item)) {
      yield item;
    }
  }
}

async function* take<T>(
  iterable: AsyncIterable<T>,
  count: number
): AsyncGenerator<T> {
  let taken = 0;
  for await (const item of iterable) {
    if (taken >= count) break;
    yield item;
    taken++;
  }
}

Functional Patterns

Higher-Order Functions

// Currying
const add = (a: number) => (b: number) => a + b;
const add5 = add(5);
console.log(add5(3)); // 8

// Pipe and compose
const pipe =
  <T>(...fns: Array<(arg: T) => T>) =>
  (value: T): T =>
    fns.reduce((acc, fn) => fn(acc), value);

const compose =
  <T>(...fns: Array<(arg: T) => T>) =>
  (value: T): T =>
    fns.reduceRight((acc, fn) => fn(acc), value);

// Usage
const processString = pipe(
  (s: string) => s.trim(),
  (s: string) => s.toLowerCase(),
  (s: string) => s.replace(/\s+/g, '-')
);

// Memoization
function memoize<Args extends unknown[], Result>(
  fn: (...args: Args) => Result
): (...args: Args) => Result {
  const cache = new Map<string, Result>();

  return (...args: Args): Result => {
    const key = JSON.stringify(args);

    if (cache.has(key)) {
      return cache.get(key)!;
    }

    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
}

// Debounce
function debounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number
): (...args: Parameters<T>) => void {
  let timeoutId: ReturnType<typeof setTimeout>;

  return (...args: Parameters<T>) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn(...args), delay);
  };
}

// Throttle
function throttle<T extends (...args: any[]) => any>(
  fn: T,
  limit: number
): (...args: Parameters<T>) => void {
  let inThrottle = false;

  return (...args: Parameters<T>) => {
    if (!inThrottle) {
      fn(...args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}

Immutable Data Patterns

// Object updates
const updateUser = (user: User, updates: Partial<User>): User => ({
  ...user,
  ...updates,
});

// Nested updates
interface State {
  users: Record<string, User>;
  settings: {
    theme: string;
    notifications: boolean;
  };
}

const updateNestedState = (
  state: State,
  userId: string,
  userUpdate: Partial<User>
): State => ({
  ...state,
  users: {
    ...state.users,
    [userId]: {
      ...state.users[userId],
      ...userUpdate,
    },
  },
});

// Array operations (immutable)
const addItem = <T>(arr: T[], item: T): T[] => [...arr, item];
const removeItem = <T>(arr: T[], index: number): T[] => [
  ...arr.slice(0, index),
  ...arr.slice(index + 1),
];
const updateItem = <T>(arr: T[], index: number, item: T): T[] => [
  ...arr.slice(0, index),
  item,
  ...arr.slice(index + 1),
];

Modern JavaScript Features

Destructuring and Spread

// Object destructuring with defaults and rename
const { name, email, role = 'user', id: odentifier } = user;

// Nested destructuring
const {
  address: { city, country },
} = user;

// Array destructuring
const [first, second, ...rest] = items;
const [, , third] = items; // Skip elements

// Function parameter destructuring
function createUser({
  name,
  email,
  role = 'user',
}: {
  name: string;
  email: string;
  role?: string;
}) {
  return { id: generateId(), name, email, role };
}

// Spread for merging
const merged = { ...defaults, ...overrides };
const combined = [...arr1, ...arr2];

Optional Chaining and Nullish Coalescing

// Optional chaining
const city = user?.address?.city;
const firstItem = items?.[0];
const result = callback?.();

// Nullish coalescing (only null/undefined)
const value = input ?? defaultValue;

// Combining them
const displayName = user?.profile?.displayName ?? user?.name ?? 'Anonymous';

// Logical assignment operators
let config = { timeout: 0 };
config.timeout ||= 5000; // Assigns if falsy (won't assign, 0 is falsy)
config.timeout ??= 5000; // Assigns if null/undefined (won't assign)
config.retries ??= 3; // Assigns (undefined)

Error Handling

// Custom error classes
class AppError extends Error {
  constructor(
    message: string,
    public code: string,
    public statusCode: number = 500
  ) {
    super(message);
    this.name = 'AppError';
    Error.captureStackTrace(this, this.constructor);
  }
}

class ValidationError extends AppError {
  constructor(
    message: string,
    public fields: Record<string, string[]>
  ) {
    super(message, 'VALIDATION_ERROR', 400);
    this.name = 'ValidationError';
  }
}

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

function ok<T>(value: T): Result<T, never> {
  return { ok: true, value };
}

function err<E>(error: E): Result<never, E> {
  return { ok: false, error };
}

// Using Result
function parseJSON<T>(json: string): Result<T, SyntaxError> {
  try {
    return ok(JSON.parse(json));
  } catch (e) {
    return err(e as SyntaxError);
  }
}

// Chaining Results
function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> {
  return result.ok ? ok(fn(result.value)) : result;
}

function flatMap<T, U, E>(
  result: Result<T, E>,
  fn: (value: T) => Result<U, E>
): Result<U, E> {
  return result.ok ? fn(result.value) : result;
}

Module Patterns

// Named exports
export const API_URL = 'https://api.example.com';
export function fetchData() {}
export class ApiClient {}

// Default export
export default class Logger {}

// Re-exports
export { UserService } from './user-service';
export { default as Logger } from './logger';
export * from './types';
export * as utils from './utils';

// Dynamic imports
async function loadModule() {
  const { default: Chart } = await import('./chart');
  return new Chart();
}

// Conditional imports
const adapter = await import(
  process.env.NODE_ENV === 'test' ? './mock-adapter' : './real-adapter'
);

Related Skills

  • [[frontend]] - React/Next.js development
  • [[backend]] - Node.js server development
  • [[testing]] - Jest, Vitest testing

FAQ

What does the javascript-typescript skill do?

Modern JavaScript and TypeScript development patterns

How do I install javascript-typescript?

Run npx skills add https://github.com/miles990/claude-software-skills --skill javascript-typescript in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/javascript-typescript/ (personal) or .claude/skills/javascript-typescript/ (project).

Which AI agents can use javascript-typescript?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is javascript-typescript safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains javascript-typescript?

It is published by miles990 in miles990/claude-software-skills. It has 83 recorded installs.

More from miles990/claude-software-skills

View all →

code-quality

miles990/claude-software-skills

Clean code principles, SOLID, and code review practices

devops-cicd

miles990/claude-software-skills

CI/CD pipelines, infrastructure as code, and deployment strategies

DevOps & Cloud606 installs

game-development

miles990/claude-software-skills

Open the skill to read its SKILL.md instructions.

Media & Creative411 installs

project-management

miles990/claude-software-skills

Open the skill to read its SKILL.md instructions.

389 installs

e-commerce

miles990/claude-software-skills

Open the skill to read its SKILL.md instructions.

376 installs

saas-platforms

miles990/claude-software-skills

Open the skill to read its SKILL.md instructions.

362 installs

Popular code quality & workflow skills

View category →

grill-me

mattpocock/skills

A relentless interview to sharpen a plan or design.

Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.

handoff

mattpocock/skills

Compact the current conversation into a handoff document for another agent to pick up.

domain-modeling

mattpocock/skills

Build and sharpen a project's domain model. Use when discussing codebase terminology, writing or editing a GLOSSARY.md, or recording or editing an ADR.

codebase-design

mattpocock/skills

Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.

diagnosing-bugs

mattpocock/skills

Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.