Agent Skill
2/7/2026

types

Master TypeScript development with type-safe patterns, generics, and modern tooling. This skill provides comprehensive guidance for TypeScript 5.9+, covering type system fundamentals (generics, mapped types, conditional types, satisfies operator), type based patterns (error handling, validation), React integration for type-safe frontends. Use when building type-safe applications, migrating JavaScript codebases, configuring modern toolchains (Vite 7, pnpm, ESLint, Vitest), implementing advanced type patterns, or comparing TypeScript with Java/Python approaches.

T
thejustinwalsh
3GitHub Stars
1Views
npx skills add thejustinwalsh/three-flatland

SKILL.md

Nametypes
DescriptionMaster TypeScript development with type-safe patterns, generics, and modern tooling. This skill provides comprehensive guidance for TypeScript 5.9+, covering type system fundamentals (generics, mapped types, conditional types, satisfies operator), type based patterns (error handling, validation), React integration for type-safe frontends. Use when building type-safe applications, migrating JavaScript codebases, configuring modern toolchains (Vite 7, pnpm, ESLint, Vitest), implementing advanced type patterns, or comparing TypeScript with Java/Python approaches.

name: types description: | Master TypeScript development with type-safe patterns, generics, and modern tooling. This skill provides comprehensive guidance for TypeScript 5.9+, covering type system fundamentals (generics, mapped types, conditional types, satisfies operator), type based patterns (error handling, validation), React integration for type-safe frontends. Use when building type-safe applications, migrating JavaScript codebases, configuring modern toolchains (Vite 7, pnpm, ESLint, Vitest), implementing advanced type patterns, or comparing TypeScript with Java/Python approaches. version: 1.0.0 category: programming-languages triggers:

  • typescript
  • ts
  • type-safe
  • generics
  • react typescript
  • typescript migration
  • tsconfig
  • type guards
  • mapped types
  • conditional types
  • satisfies operator author: Adapted from Richard Hightower license: MIT tags:
  • typescript
  • type-safety
  • react
  • vite

Types

Build type-safe applications with TypeScript 5.9+.

Compatibility: TypeScript 5.9+, Node.js 22 LTS, Vite 7, React 19

Quick Start

# Initialize TypeScript project with ESM
pnpm create vite@latest my-app --template vanilla-ts
cd my-app && pnpm install

# Configure strict TypeScript
cat > tsconfig.json << 'EOF'
{
  "compilerOptions": {
    "target": "ES2024",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}
EOF

When to Use This Skill

Use when:

  • Building type-safe applications
  • Migrating JavaScript codebases to TypeScript
  • Implementing advanced type patterns (generics, mapped types, conditional types)
  • Configuring modern TypeScript toolchains (Vite, pnpm, ESLint)
  • Designing type-safe API contracts with validation
  • Comparing TypeScript approaches with Java or Python

Project Setup Checklist

Before starting any TypeScript project:

- [ ] Use pnpm for package management (faster, disk-efficient)
- [ ] Enable strict mode in tsconfig.json
- [ ] Set up ESLint with @typescript-eslint
- [ ] Add Prettier for consistent formatting
- [ ] Configure Vitest for testing

Type System Quick Reference

Primitive Types

const name: string = "Alice";
const age: number = 30;
const active: boolean = true;
const id: bigint = 9007199254740991n;
const key: symbol = Symbol("unique");

Union and Intersection Types

// Union: value can be one of several types
type Status = "pending" | "approved" | "rejected";

// Intersection: value must satisfy all types
type Employee = Person & { employeeId: string };

// Discriminated union for type-safe handling
type Result<T> =
  | { success: true; data: T }
  | { success: false; error: string };

function handleResult<T>(result: Result<T>): T | null {
  if (result.success) {
    return result.data; // TypeScript knows data exists here
  }
  console.error(result.error);
  return null;
}

Type Guards

// typeof guard
function process(value: string | number): string {
  if (typeof value === "string") {
    return value.toUpperCase();
  }
  return value.toFixed(2);
}

// Custom type guard
interface User { type: "user"; name: string }
interface Admin { type: "admin"; permissions: string[] }

function isAdmin(person: User | Admin): person is Admin {
  return person.type === "admin";
}

The satisfies Operator (TS 5.0+)

Validate type conformance while preserving inference:

// Problem: Type assertion loses specific type info
const colors1 = {
  red: "#ff0000",
  green: "#00ff00"
} as Record<string, string>;

colors1.red.toUpperCase(); // OK, but red could be undefined

// Solution: satisfies preserves literal types
const colors2 = {
  red: "#ff0000",
  green: "#00ff00"
} satisfies Record<string, string>;

colors2.red.toUpperCase(); // OK, and TypeScript knows red exists

Generics Patterns

Basic Generic Function

function first<T>(items: T[]): T | undefined {
  return items[0];
}

const num = first([1, 2, 3]);     // number | undefined
const str = first(["a", "b"]);   // string | undefined

Constrained Generics

interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(item: T): T {
  console.log(item.length);
  return item;
}

logLength("hello");     // OK: string has length
logLength([1, 2, 3]);   // OK: array has length
logLength(42);          // Error: number has no length

Generic API Response Wrapper

interface ApiResponse<T> {
  data: T;
  status: number;
  timestamp: Date;
}

async function fetchUser(id: string): Promise<ApiResponse<User>> {
  const response = await fetch(`/api/users/${id}`);
  const data = await response.json();
  return {
    data,
    status: response.status,
    timestamp: new Date()
  };
}

Utility Types Reference

TypePurposeExample
Partial<T>All properties optionalPartial<User>
Required<T>All properties requiredRequired<Config>
Pick<T, K>Select specific propertiesPick<User, "id" | "name">
Omit<T, K>Exclude specific propertiesOmit<User, "password">
Record<K, V>Object with typed keys/valuesRecord<string, number>
ReturnType<F>Extract function return typeReturnType<typeof fn>
Parameters<F>Extract function parametersParameters<typeof fn>
Awaited<T>Unwrap Promise typeAwaited<Promise<User>>

Conditional Types

// Basic conditional type
type IsString<T> = T extends string ? true : false;

// Extract array element type
type ArrayElement<T> = T extends (infer E)[] ? E : never;

type Numbers = ArrayElement<number[]>; // number
type Strings = ArrayElement<string[]>; // string

// Practical: Extract Promise result type
type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;

Mapped Types

// Make all properties readonly
type Immutable<T> = {
  readonly [K in keyof T]: T[K];
};

// Make all properties nullable
type Nullable<T> = {
  [K in keyof T]: T[K] | null;
};

// Create getter functions for each property
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

interface Person { name: string; age: number }
type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number }

Framework Integration

React with TypeScript

// Typed functional component
interface ButtonProps {
  label: string;
  onClick: () => void;
  variant?: "primary" | "secondary";
}

const Button: React.FC<ButtonProps> = ({ label, onClick, variant = "primary" }) => (
  <button className={variant} onClick={onClick}>
    {label}
  </button>
);

// Typed hooks
const [count, setCount] = useState<number>(0);
const userRef = useRef<HTMLInputElement>(null);

Modern Toolchain (2025)

ToolVersionPurpose
TypeScript5.9+Type checking and compilation
Node.js22 LTSRuntime environment
Vite7.xBuild tool and dev server
pnpm9.xPackage manager
ESLint9.xLinting with flat config
Vitest3.xTesting framework
Prettier3.xCode formatting

ESLint Flat Config (ESLint 9+)

// eslint.config.js
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.strictTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  }
);

Migration Strategies

Incremental Migration

  1. Add allowJs: true and checkJs: false to tsconfig.json
  2. Rename files from .js to .ts one at a time
  3. Add type annotations gradually
  4. Enable stricter options incrementally

JSDoc for Gradual Typing

// Before full migration, use JSDoc
/**
 * @param {string} name
 * @param {number} age
 * @returns {User}
 */
function createUser(name, age) {
  return { name, age };
}

See patterns.md for comprehensive migration guides.

Common Mistakes

MistakeProblemFix
Using anyDefeats type safetyCore type issue, use type guards or re-deisgn api, use of any in generics is permitted when necessary
Ignoring strict modeMisses null/undefined bugsEnable all strict options
Type assertions (as)Can hide type errorsUse satisfies or guards, or identify the core type issue and refactor, do not use comment directives to skip errors
Enum for simple unionsGenerates runtime codeUse literal unions instead

Cross-Language Comparison

FeatureTypeScriptJavaPython
Type SystemStructuralNominalGradual (duck typing)
NullabilityExplicit (T | null)@Nullable annotationsOptional via typing
GenericsType-level, erasedType-level, erasedRuntime via typing
InterfacesStructural matchingMust implementProtocol (3.8+)
EnumsAvoid (use unions)First-classEnum class

Reference Files

Skills Info
Original Name:typesAuthor:thejustinwalsh