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:
function identity(value: T): T { return value; }
const num = identity(42); const str = identity("hello"); const auto = identity(true); // Type inferred: boolean
Note: using a single letter for trivial generics can be OK, but prefer giving generic arguments a relevant short name instead.
Generic Constraints:
type HasLength = { length: number; }
function logLength(item: T): T { console.log(item.length); return item; }
Multiple Type Parameters:
function merge<T, U>(obj1: T, obj2: U): T & U { return { ...obj1, ...obj2 }; }
2. Conditional Types
type IsString = T extends string ? true : false; type ReturnType = Fn extends (...args: any[]) => infer Return ? Return : never; type ToArray = Item extends any ? Item[] : never;
3. Mapped Types
type Readonly = { readonly [P in keyof T]: T[P] };
type Partial = { [P in keyof T]?: T[P] };
type Getters = { [K in keyof T as get${Capitalize<string & K>}]: () => T[K] };
type PickByType<T, U> = { [K in keyof T as T[K] extends U ? K : never]: T[K] };
4. Template Literal Types
type EventName = "click" | "focus" | "blur";
type EventHandler = on${Capitalize<EventName>};
5. Utility Types
Partial, Required, Readonly, Pick<T, K>, Omit<T, K>, Exclude<T, U>, Extract<T, U>, NonNullable, Record<K, T>
Advanced Patterns
- Type-Safe Event Emitter
- Type-Safe API Client
- Builder Pattern with Type Safety
- Deep Readonly/Partial
- Type-Safe Form Validation
- Discriminated Unions
Type Inference Techniques
inferkeyword for extracting types- Type guards with
value is Type - Assertion functions with
asserts value is Type
Strict mode
In tsconfig.json, strict mode should always be enabled. The following flags should also be on:
- "noFallthroughCasesInSwitch": true
- "noUncheckedIndexedAccess": true
- "noPropertyAccessFromIndexSignature": true
Don't type-cast catch (err: unknown) {}, err is already unknown
in strict mode: catch (err) {}.
Best Practices
- Use
unknownoverany - Use
typeoverinterfacefor object shapes - Use
interfacefor declaration-mergeable types (extensible in userland) - Leverage type inference
- Create helper types for reuse
- Use const assertions
- Avoid type assertions — use type guards
- Use tsconfig strict settings eagerly
- Document complex types
- Use strict mode
- Test your types