Earn 30% Commission for Life

Learn More
logo
TypeScript

TypeScript Advanced Types and Patterns

Explore advanced TypeScript features including conditional types, mapped types, and complex type patterns.

December 3, 2024
9 min read
2,198 views
164
22
Lisa Wang
Lisa Wang

TypeScript expert and type system enthusiast. Helps teams leverage TypeScript's advanced features for better code safety.

TypeScript Advanced Types and Patterns

TypeScript's type system is incredibly powerful and expressive. Beyond basic type annotations, TypeScript offers advanced features that can help you create more robust, maintainable code. This guide explores some of the most powerful advanced TypeScript patterns.

Conditional Types

Conditional types allow you to create types that depend on conditions, enabling powerful type transformations.

// Basic conditional type
type IsArray = T extends any[] ? true : false;

type Test1 = IsArray; // true
type Test2 = IsArray;   // false

// Extracting types from function signatures
type ReturnType = T extends (...args: any[]) => infer R ? R : never;

type FunctionReturn = ReturnType<() => string>; // string

// Recursive conditional types
type Flatten = T extends (infer U)[] 
  ? Flatten 
  : T;

type Deep = Flatten; // string

Mapped Types

Mapped types create new types by transforming properties of existing types.

// Making all properties optional
type Partial = {
  [P in keyof T]?: T[P];
};

// Making all properties required
type Required = {
  [P in keyof T]-?: T[P];
};

// Custom mapped type for API responses
type ApiResponse = {
  [K in keyof T]: {
    value: T[K];
    loading: boolean;
    error: string | null;
  };
};

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

type UserApiState = ApiResponse;
// Results in:
// {
//   id: { value: number; loading: boolean; error: string | null };
//   name: { value: string; loading: boolean; error: string | null };
//   email: { value: string; loading: boolean; error: string | null };
// }

Template Literal Types

Create types based on string patterns and manipulations.

// Basic template literal types
type EventName = `on${Capitalize}`;

type ButtonEvents = EventName<'click' | 'hover'>; 
// 'onClick' | 'onHover'

// CSS property types
type CSSProperty = `--${string}`;
type CSSValue = string | number;

interface CSSProperties {
  [key: CSSProperty]: CSSValue;
}

// API endpoint types
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = `/api/${T}`;

type UserEndpoints = Endpoint<'users' | 'users/profile'>; 
// '/api/users' | '/api/users/profile'

Utility Types and Type Manipulation

Leverage TypeScript's built-in utility types and create your own for common patterns.

// Pick specific properties
type UserBasicInfo = Pick;

// Omit specific properties
type CreateUserRequest = Omit;

// Create union types from object keys
type UserKeys = keyof User; // 'id' | 'name' | 'email'

// Create types from value types
type UserValues = User[keyof User]; // number | string

// Record type for key-value mappings
type UserRoles = Record;

// Extract function parameters
type Parameters any> = 
  T extends (...args: infer P) => any ? P : never;

function createUser(name: string, email: string, age: number) {
  // implementation
}

type CreateUserParams = Parameters; 
// [string, string, number]

Advanced Pattern: Builder Pattern with Types

Use TypeScript's type system to create type-safe builder patterns.

interface QueryConfig {
  select?: string[];
  where?: Record;
  orderBy?: string;
  limit?: number;
}

class QueryBuilder {
  constructor(private config: T = {} as T) {}

  select(...fields: K): QueryBuilder {
    return new QueryBuilder({ ...this.config, select: fields });
  }

  where>(conditions: W): QueryBuilder {
    return new QueryBuilder({ ...this.config, where: conditions });
  }

  orderBy(field: O): QueryBuilder {
    return new QueryBuilder({ ...this.config, orderBy: field });
  }

  build(): T {
    return this.config;
  }
}

// Usage with full type safety
const query = new QueryBuilder()
  .select('id', 'name', 'email')
  .where({ status: 'active' })
  .orderBy('created_at')
  .build();
  
// Type is inferred as:
// {
//   select: ['id', 'name', 'email'];
//   where: { status: string };
//   orderBy: 'created_at';
// }

Conclusion

Advanced TypeScript types unlock powerful patterns for creating type-safe, expressive APIs. While these features can seem complex, they provide incredible value in catching errors at compile time and creating self-documenting code. Start with simpler patterns and gradually incorporate more advanced techniques as you become comfortable with TypeScript's type system.

Access Our Premium Resources (Free)

Get unlimited access to all our courses, tutorials, and resources. Start your learning journey today with our comprehensive training materials.

No credit card required • Access to 6+ resources • Community support

Related Articles

Advanced JavaScript ES6+ Features You Need to Know
JavaScript

Advanced JavaScript ES6+ Features You Need to Know

5 min read
Mastering CSS Grid Layout for Modern Web Design
CSS

Mastering CSS Grid Layout for Modern Web Design

7 min read
Node.js Authentication with JWT and Best Practices
Node.js

Node.js Authentication with JWT and Best Practices

8 min read