AI agent skill

Typescript Advanced Types

Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.

·

When to use this skill

Use Typescript Advanced Types when an AI agent needs a reusable SKILL.md workflow for this job: Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.

When not to use it

Skip Typescript Advanced Types when the task is outside the coding category, or when a more specific skill in this directory already covers the same workflow with clearer triggers.

How to install

  1. Personal install: create ~/.claude/skills/typescript-advanced-types/SKILL.md (and any bundled scripts) so Claude Code, Claude Desktop, and compatible agents can load it in every project.
  2. Project install: commit the same folder at .claude/skills/typescript-advanced-types/ so teammates get the skill with the repo.
  3. Restart the agent session after copying files so it re-scans the skills directory, then ask for the task in words that match the skill description.

Full install guide for Claude, Cursor, and Codex

What this skill does

# TypeScript Advanced Types

Comprehensive guidance for mastering TypeScript's advanced type system including generics, conditional types, mapped types, template literal types, and utility types for building robust, type-safe applications.

## When to Use This Skill

- Building type-safe libraries or frameworks - Creating reusable generic components - Implementing complex type inference logic - Designing type-safe API clients - Building form validation systems - Creating strongly-typed configuration objects - Implementing type-safe state management - Migrating JavaScript codebases to TypeScript

## Core Concepts

### 1. Generics

**Purpose:** Create reusable, type-flexible components while maintaining type safety.

**Basic Generic Function:**

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

const num = identity<number>(42); // Type: number const str = identity<string>("hello"); // Type: string const auto = identity(true); // Type inferred: boolean ```

**Generic Constraints:**

```typescript 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({ length: 10 }); // OK: object has length // logLength(42); // Error: number has no length ```

**Multiple Type Parameters:**

```typescript function merge<T, U>(obj1: T, obj2: U): T & U { return { ...obj1, ...obj2 }; }

const merged = merge({ name: "John" }, { age: 30 }); // Type: { name: string } & { age: number } ```

### 2. Conditional Types

**Purpose:** Create types that depend on conditions, enabling sophisticated type logic.

**Basic Conditional Type:**

```typescript type IsString<T> = T extends string ? true : false;

type A = IsString<string>; // true type B = IsString<number>; // false ```

**Extracting Return Types:**

```typescript type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

function getUser() { return { id: 1, name: "John" }; }

type User = ReturnType<typeof getUser>; // Type: { id: number; name: string; } ```

**Distributive Conditional Types:**

```typescript type ToArray<T> = T extends any ? T[] : never;

type StrOrNumArray = ToArray<string | number>; // Type: string[] | number[] ```

**Nested Conditions:**

```typescript type TypeName<T> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : T extends undefined ? "undefined" : T extends Function ? "function" : "object";

type T1 = TypeName<string>; // "string" type T2 = TypeName<() => void>; // "function" ```

### 3. Mapped Types

**Purpose:** Transform existing types by iterating over their properties.

**Basic Mapped Type:**

```typescript type Readonly<T> = { readonly [P in keyof T]: T[P]; };

interface User { id: number; name: string; }

type ReadonlyUser = Readonly<User>; // Type: { readonly id: number; readonly name: string; } ```

**Optional Properties:**

```typescript type Partial<T> = { [P in keyof T]?: T[P]; };

type PartialUser = Partial<User>; // Type: { id?: number; name?: string; } ```

**Key Remapping:**

```typescript type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]; };

interface Person { name: string; age: number; }

type PersonGetters = Getters<Person>; // Type: { getName: () => string; getAge: () => number; } ```

**Filtering Properties:**

```typescript type PickByType<T, U> = { [K in keyof T as T[K] extends U ? K : never]: T[K]; };

interface Mixed { id: number; name: string; age: number; active: boolean; }

type OnlyNumbers = PickByType<Mixed, number>; // Type: { id: number; age: number; } ```

### 4. Template Literal Types

**Purpose:** Create string-based types with pattern matching and transformation.

**Basic Template Literal:**

```typescript type EventName = "click" | "focus" | "blur"; type EventHandler = `on${Capitalize<EventName>}`; // Type: "onClick" | "onFocus" | "onBlur" ```

**String Manipulation:**

```typescript type UppercaseGreeting = Uppercase<"hello">; // "HELLO" type LowercaseGreeting = Lowercase<"HELLO">; // "hello" type CapitalizedName = Capitalize<"john">; // "John" type UncapitalizedName = Uncapitalize<"John">; // "john" ```

**Path Building:**

```typescript type Path<T> = T extends object ? { [K in keyof T]: K extends string ? `${K}` | `${K}.${Path<T[K]>}` : never; }[keyof T] : never;

interface Config { server: { host: string; port: number; }; database: { url: string; }; }

type ConfigPath = Path<Config>; // Type: "server" | "database" | "server.host" | "server.port" | "database.url" ```

### 5. Utility Types

**Built-in Utility Types:**

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

// Required<T> - Make all properties required type RequiredUser = Required<PartialUser>;

// Readonly<T> - Make all properties readonly type ReadonlyUser = Readonly<User>;

// Pick<T, K> - Select specific properties type UserName = Pick<User, "name" | "email">;

// Omit<T, K> - Remove specific properties type UserWithoutPassword = Omit<User, "password">;

// Exclude<T, U> - Exclude types from union type T1 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"

// Extract<T, U> - Extract types from union type T2 = Extract<"a" | "b" | "c", "a" | "b">; // "a" | "b"

// NonNullable<T> - Exclude null and undefined type T3 = NonNullable<string | null | undefined>; // string

// Record<K, T> - Create object type with keys K and values T type PageInfo = Record<"home" | "about", { title: string }>; ```

## Detailed worked examples and patterns

Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.

## Best Practices

1. **Use `unknown` over `any`**: Enforce type checking 2. **Prefer `interface` for object shapes**: Better error messages 3. **Use `type` for unions and complex types**: More flexible 4. **Leverage type inference**: Let TypeScript infer when possible 5. **Create helper types**: Build reusable type utilities 6. **Use const assertions**: Preserve literal types 7. **Avoid type assertions**: Use type guards instead 8. **Document complex types**: Add JSDoc comments 9. **Use strict mode**: Enable all strict compiler options 10. **Test your types**: Use type tests to verify type behavior

## Type Testing

```typescript // Type assertion tests type AssertEqual<T, U> = [T] extends [U] ? [U] extends [T] ? true : false : false;

type Test1 = AssertEqual<string, string>; // true type Test2 = AssertEqual<string, number>; // false type Test3 = AssertEqual<string | number, string>; // false

// Expect error helper type ExpectError<T extends never> = T;

// Example usage type ShouldError = ExpectError<AssertEqual<string, number>>; ```

## Common Pitfalls

1. **Over-using `any`**: Defeats the purpose of TypeScript 2. **Ignoring strict null checks**: Can lead to runtime errors 3. **Too complex types**: Can slow down compilation 4. **Not using discriminated unions**: Misses type narrowing opportunities 5. **Forgetting readonly modifiers**: Allows unintended mutations 6. **Circular type references**: Can cause compiler errors 7. **Not handling edge cases**: Like empty arrays or null values

## Performance Considerations

- Avoid deeply nested conditional types - Use simple types when possible - Cache complex type computations - Limit recursion depth in recursive types - Use build tools to skip type checking in production

Intended uses

  • Building type-safe libraries or frameworks
  • Creating reusable generic components
  • Implementing complex type inference logic
  • Designing type-safe API clients
  • Building form validation systems
  • Creating strongly-typed configuration objects
  • Implementing type-safe state management
  • Migrating JavaScript codebases to TypeScript

Related skills

Related skills in this directory, for comparison before you install another skill.

coding

Add Backend

Guide for adding a backend (Rust or Python) to the agent-sec-core security middleware. Use when creating new backends, integrating Rust or Python code into the security middleware, or extending with new backend actions.

View skill

coding

Agent Device

Drive iOS and Android devices for the Expensify App - testing, debugging, performance profiling, bug reproduction, and feature verification. Use when the developer needs to interact with the mobile app on a device.

View skill

Ranked Claude skills