references/advanced-generics.md
# Advanced Generics
**Generic constraints and inference:**
## Basic Constraints
```typescript
// Constrain to objects with specific keys
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: 'John', age: 30 };
const name = getProperty(user, 'name'); // Type: string
// const invalid = getProperty(user, 'invalid'); // Error
// Multiple constraints
function merge<T extends object, U extends object>(
obj1: T,
obj2: U
): T & U {
return { ...obj1, ...obj2 };
}
```
## Generic Inference
```typescript
// Infer from function implementation
function createAction<T extends string, P>(
type: T,
payload: P
) {
return { type, payload };
}
const action = createAction('UPDATE_USER', { id: 1, name: 'John' });
// Type: { type: 'UPDATE_USER'; payload: { id: number; name: string } }
// Infer generic types from usage
function useState<S>(
initialState: S | (() => S)
): [S, (newState: S) => void] {
// Implementation
}
const [count, setCount] = useState(0); // S inferred as number
const [user, setUser] = useState({ name: 'John' }); // S inferred as { name: string }
```
## Higher-Kinded Types Pattern
```typescript
// Type-safe data structures
interface Functor<F> {
map<A, B>(fa: F extends { value: any } ? F : never, f: (a: A) => B): any;
}
interface Box<T> {
value: T;
}
const boxFunctor: Functor<Box<any>> = {
map<A, B>(fa: Box<A>, f: (a: A) => B): Box<B> {
return { value: f(fa.value) };
}
};
```
## Conditional Generic Types
```typescript
// Return type varies based on parameter
type ApiResponse<T extends string> =
T extends 'json' ? object :
T extends 'text' ? string :
T extends 'blob' ? Blob :
never;
async function fetch<T extends 'json' | 'text' | 'blob'>(
url: string,
type: T
): Promise<ApiResponse<T>> {
// Implementation
}
const json = await fetch('/api', 'json'); // Type: object
const text = await fetch('/api', 'text'); // Type: string
const blob = await fetch('/api', 'blob'); // Type: Blob
```
references/branded-types.md
# Branded Types
**Create nominal types for type safety:**
## Preventing Primitive Mixing
```typescript
// Prevent mixing similar primitive types
type UserId = string & { readonly __brand: 'UserId' };
type PostId = string & { readonly __brand: 'PostId' };
function createUserId(id: string): UserId {
return id as UserId;
}
function createPostId(id: string): PostId {
return id as PostId;
}
function getUser(userId: UserId): User {
// Implementation
}
const userId = createUserId('user-123');
const postId = createPostId('post-456');
getUser(userId); // Valid
// getUser(postId); // Type error: PostId not assignable to UserId
```
## Validation with Branded Types
```typescript
type ValidEmail = string & { readonly __brand: 'ValidEmail' };
type ValidURL = string & { readonly __brand: 'ValidURL' };
function validateEmail(email: string): ValidEmail | null {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email) ? (email as ValidEmail) : null;
}
function sendEmail(to: ValidEmail, subject: string, body: string) {
// Guaranteed to have valid email
}
const email = validateEmail('user@example.com');
if (email) {
sendEmail(email, 'Hello', 'World');
}
```
## Benefits
- Compile-time prevention of ID mixing
- Self-documenting code through type names
- Enforced validation at boundaries
- Zero runtime overhead
references/builder-pattern.md
# Builder Pattern with Types
**Type-safe fluent APIs:**
## Query Builder Example
```typescript
interface QueryBuilder<TSelect = unknown, TWhere = unknown> {
select<T>(): QueryBuilder<T, TWhere>;
where<T>(): QueryBuilder<TSelect, T>;
execute(): TSelect extends unknown ? never : Promise<TSelect[]>;
}
// Usage ensures select() called before execute()
const results = await query
.select<User>()
.where<{ age: number }>()
.execute(); // Type: Promise<User[]>
// query.execute(); // Error: select() not called
```
## Progressive Builder Types
```typescript
interface ConfigBuilder<
THost extends string | undefined = undefined,
TPort extends number | undefined = undefined
> {
host: THost;
port: TPort;
withHost<H extends string>(host: H): ConfigBuilder<H, TPort>;
withPort<P extends number>(port: P): ConfigBuilder<THost, P>;
build: THost extends string
? TPort extends number
? () => { host: THost; port: TPort }
: never
: never;
}
const config = new ConfigBuilder()
.withHost('localhost')
.withPort(3000)
.build(); // Valid
// new ConfigBuilder().build(); // Error: host and port required
```
## Type State Pattern
```typescript
// Enforce method call order at compile time
interface EmptyBuilder {
addItem<T>(item: T): FilledBuilder<T>;
}
interface FilledBuilder<T> {
addItem(item: T): FilledBuilder<T>;
build(): T[];
}
// Must call addItem() before build()
const items = builder
.addItem('first')
.addItem('second')
.build(); // Valid
// builder.build(); // Error: can't build empty
```
references/common-pitfalls.md
# Common Pitfalls
## Type Assertions vs Type Guards
```typescript
// Bad - unsafe type assertion
const value = input as string;
// Good - safe type guard
function assertString(value: unknown): asserts value is string {
if (typeof value !== 'string') {
throw new Error('Not a string');
}
}
assertString(input);
// input is now narrowed to string
```
## Any vs Unknown
```typescript
// Bad - loses type safety
function process(data: any) {
return data.toUpperCase(); // No type checking
}
// Good - maintains type safety
function processUnknown(data: unknown) {
if (typeof data === 'string') {
return data.toUpperCase(); // Type guard required
}
throw new Error('Expected string');
}
```
## Overusing Generics
```typescript
// Bad - unnecessary complexity
function add<T extends number, U extends number>(a: T, b: U): number {
return a + b;
}
// Good - simple and clear
function add(a: number, b: number): number {
return a + b;
}
```
## Incorrect Type Narrowing
```typescript
// Bad - doesn't narrow type
function isString(value: any): boolean {
return typeof value === 'string';
}
// Good - properly narrows type
function isString(value: unknown): value is string {
return typeof value === 'string';
}
```
## Forgetting Readonly
```typescript
// Bad - mutable when should be immutable
interface Config {
apiUrl: string;
timeout: number;
}
// Good - prevent accidental mutations
interface Config {
readonly apiUrl: string;
readonly timeout: number;
}
```
## Enum Pitfalls
```typescript
// Bad - numeric enums allow invalid values
enum Status {
Active,
Inactive
}
const status: Status = 999; // Valid but meaningless
// Good - use string enums or const objects
enum Status {
Active = 'ACTIVE',
Inactive = 'INACTIVE'
}
// Or use const object with as const
const Status = {
Active: 'ACTIVE',
Inactive: 'INACTIVE'
} as const;
```
## Not Using Strict Mode
```typescript
// Always enable in tsconfig.json
{
"compilerOptions": {
"strict": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true
}
}
```
## Type vs Interface Confusion
```typescript
// Use type for unions, intersections, utilities
type ID = string | number;
type Point = { x: number } & { y: number };
// Use interface for object shapes that may be extended
interface User {
id: ID;
name: string;
}
interface Admin extends User {
permissions: string[];
}
```
references/conditional-types.md
# Conditional Types
**Type selection based on conditions:**
```typescript
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
// Extract function return types
type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;
type Fn = () => { name: string; age: number };
type Result = ReturnTypeOf<Fn>; // { name: string; age: number }
// Extract array element types
type ElementOf<T> = T extends (infer E)[] ? E : never;
type Items = ElementOf<string[]>; // string
```
## Use Cases
- Type transformation and extraction
- Conditional API responses based on request types
- Generic utility type creation
- Framework integration types
references/decorators.md
# Decorators (Stage 3)
**Class and method decorators for cross-cutting concerns:**
## Method Decorators
```typescript
// Method decorator for logging
function log(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const original = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Calling ${propertyKey} with`, args);
const result = original.apply(this, args);
console.log(`Result:`, result);
return result;
};
return descriptor;
}
class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
}
```
## Property Decorators
```typescript
// Property decorator for validation
function validate(validator: (value: any) => boolean) {
return function(target: any, propertyKey: string) {
let value = target[propertyKey];
Object.defineProperty(target, propertyKey, {
get: () => value,
set: (newValue) => {
if (!validator(newValue)) {
throw new Error(`Invalid value for ${propertyKey}`);
}
value = newValue;
}
});
};
}
class User {
@validate(email => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))
email: string;
}
```
## Class Decorators
```typescript
// Class decorator for metadata
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class SealedClass {
constructor(public name: string) {}
}
```
## Decorator Factories
```typescript
// Decorator with parameters
function component(config: { selector: string }) {
return function(constructor: Function) {
constructor.prototype.selector = config.selector;
};
}
@component({ selector: 'app-user' })
class UserComponent {
// selector property added at runtime
}
```
## Common Use Cases
- **Logging**: Automatic method call logging
- **Validation**: Property value validation
- **Memoization**: Cache method results
- **Authorization**: Check permissions before execution
- **Dependency Injection**: Inject dependencies into classes
- **Metadata**: Attach runtime metadata for frameworks
references/discriminated-unions.md
# Discriminated Unions
**Type-safe state machines and variants:**
## State Machines
```typescript
// State machine with exhaustive checking
type LoadingState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: string[] }
| { status: 'error'; error: Error };
function renderState(state: LoadingState): string {
switch (state.status) {
case 'idle':
return 'Not started';
case 'loading':
return 'Loading...';
case 'success':
return `Loaded ${state.data.length} items`;
case 'error':
return `Error: ${state.error.message}`;
}
// Exhaustiveness checking ensures all cases handled
}
```
## Action Types
```typescript
// API action types
type Action =
| { type: 'FETCH_USER'; payload: { userId: string } }
| { type: 'UPDATE_USER'; payload: { userId: string; data: Partial<User> } }
| { type: 'DELETE_USER'; payload: { userId: string } }
| { type: 'CLEAR_USERS' };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'FETCH_USER':
// action.payload is { userId: string }
return { ...state, loading: true };
case 'UPDATE_USER':
// action.payload is { userId: string; data: Partial<User> }
return updateUser(state, action.payload);
case 'DELETE_USER':
return deleteUser(state, action.payload.userId);
case 'CLEAR_USERS':
// action has no payload
return { ...state, users: [] };
}
}
```
## Best Practices
- Always include a discriminant property (e.g., `status`, `type`)
- Use string literal types for discriminant values
- Enable `strictNullChecks` for exhaustiveness checking
- Use `never` to ensure all cases are handled
references/mapped-types.md
# Mapped Types
**Transform object types systematically:**
```typescript
// Make all properties optional
type Partial<T> = {
[P in keyof T]?: T[P];
};
// Make all properties readonly
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// Pick specific properties
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface User {
id: number;
name: string;
email: string;
password: string;
}
// Create API response type
type UserResponse = Omit<User, 'password'>;
// Create update type (all optional)
type UserUpdate = Partial<User>;
// Create creation type (no id)
type UserCreate = Omit<User, 'id'>;
```
## Advanced Mapping
```typescript
// Add prefix to all keys
type Prefixed<T, Prefix extends string> = {
[K in keyof T as `${Prefix}${string & K}`]: T[K];
};
type Events = {
click: MouseEvent;
focus: FocusEvent;
};
type Handlers = Prefixed<Events, 'on'>;
// { onclick: MouseEvent; onfocus: FocusEvent }
```
references/performance-best-practices.md
# Performance Best Practices
## Avoid Excessive Type Complexity
**Keep types simple and composable:**
```typescript
// Bad - deeply nested types
type Complex<T> = T extends Array<infer U>
? U extends Array<infer V>
? V extends Array<infer W>
? W extends Array<infer X>
? X
: never
: never
: never
: never;
// Good - iterative approach
type ElementType<T> = T extends (infer E)[] ? E : T;
type Deep1<T> = ElementType<T>;
type Deep2<T> = ElementType<Deep1<T>>;
```
## Use Type Aliases for Reusability
**Extract common patterns:**
```typescript
// Define once, reuse everywhere
type ID = string | number;
type Timestamp = number;
type Optional<T> = T | null | undefined;
interface User {
id: ID;
createdAt: Timestamp;
lastLogin: Optional<Timestamp>;
}
```
## Leverage Inference
**Let TypeScript infer when possible:**
```typescript
// Don't over-annotate
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' }
]; // Type inferred automatically
// Use inference in generics
function identity<T>(value: T): T {
return value;
}
const num = identity(42); // T inferred as 42 (literal type)
```
## Avoid Type Computation Overhead
```typescript
// Bad - expensive type computation on every use
type ExpensiveUnion<T> = T extends any
? { [K in keyof T]: SomeComplexType<T[K]> }
: never;
// Good - compute once, reuse
type PrecomputedType = ExpensiveUnion<MyType>;
function useType(value: PrecomputedType) { }
```
## Use Index Signatures Wisely
```typescript
// Bad - loses type safety
interface LooseMap {
[key: string]: any;
}
// Good - constrained types
interface TypedMap {
[key: string]: string | number;
}
// Better - use Record for known types
type StrictMap = Record<'id' | 'name' | 'age', string | number>;
```
## Optimize Union Types
```typescript
// Bad - large union causes slow checking
type ManyStrings = 'a' | 'b' | 'c' | /* ...100 more */ | 'z';
// Good - use branded types or enums for large sets
enum StringEnum {
A = 'a',
B = 'b',
// ...
}
```
references/template-literal-types.md
# Template Literal Types
**String type manipulation at compile time:**
```typescript
// Event handler types
type EventNames = 'click' | 'focus' | 'blur';
type EventHandlers = `on${Capitalize<EventNames>}`;
// 'onClick' | 'onFocus' | 'onBlur'
// URL path types
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = `/api/${'users' | 'posts' | 'comments'}`;
type Route = `${HTTPMethod} ${Endpoint}`;
// 'GET /api/users' | 'POST /api/users' | ...
// CSS property types
type CSSUnit = 'px' | 'em' | 'rem' | '%';
type Size = `${number}${CSSUnit}`;
const width: Size = '100px'; // Valid
const height: Size = '2em'; // Valid
// const invalid: Size = '100'; // Error
```
## Nested Template Literals
```typescript
type DeepKey<T> = T extends object
? {
[K in keyof T & string]: K | `${K}.${DeepKey<T[K]>}`;
}[keyof T & string]
: never;
interface Config {
database: {
host: string;
port: number;
credentials: {
username: string;
password: string;
};
};
}
type ConfigKeys = DeepKey<Config>;
// 'database' | 'database.host' | 'database.port' |
// 'database.credentials' | 'database.credentials.username' | ...
```
references/testing-types.md
# Testing Type-Safe Code
## Type Assertion Tests
```typescript
// Type equality checker
type AssertEqual<T, U> = T extends U ? (U extends T ? true : false) : false;
type Test1 = AssertEqual<Pick<User, 'name'>, { name: string }>; // true
type Test2 = AssertEqual<string, number>; // false
```
## Compile-Time Validation
```typescript
// Expect type to match
function expectType<T>(value: T): T {
return value;
}
const user: User = { id: 1, name: 'John', email: 'john@example.com', password: 'secret' };
expectType<UserResponse>(user); // Error: password should not exist
```
## Test Helper Types
```typescript
// Assert never (for exhaustiveness checking)
type AssertNever<T extends never> = T;
// Assert extends
type AssertExtends<T, U extends T> = U;
// Assert assignable
type AssertAssignable<T, U> = U extends T ? true : false;
```
## Runtime Type Testing
```typescript
import { expectType, expectError, expectAssignable } from 'tsd';
// Test type inference
const result = identity(42);
expectType<number>(result);
// Test error cases
// @ts-expect-error
expectError(getUser('invalid-id'));
// Test assignability
interface Base { id: number; }
interface Extended extends Base { name: string; }
expectAssignable<Base>({} as Extended);
```
## Property-Based Type Testing
```typescript
// Test all properties of a type
type TestUserProperties = {
[K in keyof User]: User[K] extends string | number ? true : false;
};
// Ensure required properties exist
type RequiredFields = Required<Pick<User, 'id' | 'name' | 'email'>>;
```
## Testing Discriminated Unions
```typescript
type State =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: string };
// Test exhaustiveness
function testExhaustive(state: State) {
switch (state.status) {
case 'idle':
case 'loading':
case 'success':
return;
default:
// Should be never
const _exhaustive: never = state;
return _exhaustive;
}
}
```
## Type Coverage Tools
Use `type-coverage` to ensure high type safety:
```bash
npm install --save-dev type-coverage
# Check type coverage
npx type-coverage
# Require 100% coverage
npx type-coverage --at-least 100
```
## Testing Frameworks
- **tsd**: Test TypeScript type definitions
- **dtslint**: Linter for .d.ts files
- **type-coverage**: Measure type coverage percentage
- **ts-expect**: Runtime type checking for tests
references/type-guards.md
# Type Guards
**Runtime type checking with type narrowing:**
## Basic Type Guards
```typescript
// Basic type guard
function isString(value: unknown): value is string {
return typeof value === 'string';
}
// Discriminated union guard
interface Success {
status: 'success';
data: string;
}
interface Error {
status: 'error';
message: string;
}
type Result = Success | Error;
function isSuccess(result: Result): result is Success {
return result.status === 'success';
}
function handleResult(result: Result) {
if (isSuccess(result)) {
console.log(result.data); // Type narrowed to Success
} else {
console.log(result.message); // Type narrowed to Error
}
}
```
## Generic Type Guards
```typescript
function isArrayOf<T>(
value: unknown,
check: (item: unknown) => item is T
): value is T[] {
return Array.isArray(value) && value.every(check);
}
const data: unknown = [1, 2, 3];
if (isArrayOf(data, (x): x is number => typeof x === 'number')) {
data.forEach(n => n.toFixed(2)); // Type: number[]
}
```
## Assertion Functions
```typescript
// Type assertion function
function assertString(value: unknown): asserts value is string {
if (typeof value !== 'string') {
throw new Error('Not a string');
}
}
const input: unknown = 'hello';
assertString(input);
// input is now narrowed to string
input.toUpperCase(); // Valid
```
references/type-inference.md
# Type Inference Techniques
**Leverage TypeScript's type inference:**
## Const Assertions
```typescript
// Without const assertion
const colors1 = ['red', 'green', 'blue'];
// Type: string[]
// With const assertion
const colors2 = ['red', 'green', 'blue'] as const;
// Type: readonly ['red', 'green', 'blue']
// Narrow object types
const config = {
endpoint: '/api/users',
method: 'GET'
} as const;
// Type: { readonly endpoint: '/api/users'; readonly method: 'GET' }
```
## Inference from Implementation
```typescript
// Infer from function implementation
function createAction<T extends string, P>(
type: T,
payload: P
) {
return { type, payload };
}
const action = createAction('UPDATE_USER', { id: 1, name: 'John' });
// Type: { type: 'UPDATE_USER'; payload: { id: number; name: string } }
```
## Inference with Generics
```typescript
// Let TypeScript infer generic types
function identity<T>(value: T): T {
return value;
}
const num = identity(42); // T inferred as 42 (literal type)
const str = identity('hello'); // T inferred as 'hello'
// Inference from array methods
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2); // Type: number[]
```
## Discriminated Union Inference
```typescript
// Use in discriminated unions
type Action =
| ReturnType<typeof createAction<'INCREMENT'>>
| ReturnType<typeof createAction<'DECREMENT'>>;
function reducer(state: number, action: Action): number {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
}
}
```
## Tuple Inference
```typescript
// Infer tuple types
function tuple<T extends any[]>(...args: T): T {
return args;
}
const pair = tuple(1, 'hello'); // Type: [number, string]
const triple = tuple(1, 'hello', true); // Type: [number, string, boolean]
```
## Contextual Typing
```typescript
// Type inferred from context
interface Point {
x: number;
y: number;
}
const points: Point[] = [
{ x: 0, y: 0 }, // Type inferred from array type
{ x: 1, y: 1 }
];
// Callback inference
['1', '2', '3'].map(str => parseInt(str)); // str inferred as string
```
references/utility-types.md
# Utility Types Composition
**Combine utility types for complex transformations:**
## Deep Transformations
```typescript
// Deep partial
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
// Make specific keys required
type RequireKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
interface User {
id?: number;
name?: string;
email?: string;
}
type UserWithId = RequireKeys<User, 'id'>;
// { id: number; name?: string; email?: string }
```
## Function Type Utilities
```typescript
// Extract function parameter types
type Parameters<T extends (...args: any[]) => any> =
T extends (...args: infer P) => any ? P : never;
function processUser(id: number, name: string): void {}
type ProcessUserParams = Parameters<typeof processUser>;
// [number, string]
// Extract return type
type ReturnType<T extends (...args: any[]) => any> =
T extends (...args: any[]) => infer R ? R : never;
```
## Advanced Transformations
```typescript
// Flatten nested types
type Flatten<T> = T extends any[] ? T[number] : T;
type Nested = (string | number)[][];
type Flat = Flatten<Nested>; // (string | number)[]
// Exclude nullable values
type NonNullable<T> = T extends null | undefined ? never : T;
// Recursive type definitions
type JSONValue =
| string
| number
| boolean
| null
| JSONValue[]
| { [key: string]: JSONValue };
```
## Readonly Utilities
```typescript
// Deep readonly
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object
? DeepReadonly<T[P]>
: T[P];
};
// Mutable (remove readonly)
type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
```
## Key Manipulation
```typescript
// Extract keys of specific type
type KeysOfType<T, U> = {
[K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
interface Example {
name: string;
age: number;
active: boolean;
count: number;
}
type StringKeys = KeysOfType<Example, string>; // 'name'
type NumberKeys = KeysOfType<Example, number>; // 'age' | 'count'
```
SKILL.md
---
name: typescript-advanced-patterns
description: Advanced TypeScript patterns for type-safe, maintainable code using sophisticated type system features. Use when building type-safe APIs, implementing complex domain models, or leveraging TypeScript's advanced type capabilities.
keywords:
- TypeScript
- advanced types
- branded types
- conditional types
- discriminated union
- generic constraints
- mapped types
- template literal types
- type guard
- type inference
file_patterns:
- '**/*.ts'
- '**/*.tsx'
- '**/package.json'
- '**/tsconfig.json'
confidence: 0.78
---
# TypeScript Advanced Patterns
Expert guidance for leveraging TypeScript's advanced type system features to build robust, type-safe applications with sophisticated type inference, compile-time guarantees, and maintainable domain models.
## When to Use This Skill
- Building type-safe APIs with strict contracts and validation
- Implementing complex domain models with compile-time enforcement
- Creating reusable libraries with sophisticated type inference
- Enforcing business rules through the type system
- Building type-safe state machines and builders
- Developing framework integrations requiring advanced types
- Implementing runtime validation with type-level guarantees
## Core Concepts
TypeScript's type system enables compile-time safety through:
1. **Conditional Types**: Type selection based on conditions (type-level if/else)
2. **Mapped Types**: Transform object types systematically (Partial, Readonly, Pick, Omit)
3. **Template Literal Types**: String manipulation at compile time
4. **Type Guards**: Runtime checking with type narrowing (`value is Type`)
5. **Discriminated Unions**: Type-safe state machines with exhaustiveness checking
6. **Branded Types**: Nominal types for preventing primitive mixing
7. **Builder Pattern**: Type-safe fluent APIs with progressive type constraints
8. **Advanced Generics**: Constraints, inference, and higher-kinded type patterns
9. **Utility Types**: Deep transformations and compositions
10. **Type Inference**: Const assertions and contextual typing
## Quick Reference
Load detailed references on-demand:
| Topic | Reference File |
|-------|----------------|
| Conditional Types | `skills/typescript-advanced-patterns/references/conditional-types.md` |
| Mapped Types | `skills/typescript-advanced-patterns/references/mapped-types.md` |
| Template Literal Types | `skills/typescript-advanced-patterns/references/template-literal-types.md` |
| Type Guards | `skills/typescript-advanced-patterns/references/type-guards.md` |
| Discriminated Unions | `skills/typescript-advanced-patterns/references/discriminated-unions.md` |
| Branded Types | `skills/typescript-advanced-patterns/references/branded-types.md` |
| Builder Pattern | `skills/typescript-advanced-patterns/references/builder-pattern.md` |
| Advanced Generics | `skills/typescript-advanced-patterns/references/advanced-generics.md` |
| Utility Types | `skills/typescript-advanced-patterns/references/utility-types.md` |
| Type Inference | `skills/typescript-advanced-patterns/references/type-inference.md` |
| Decorators | `skills/typescript-advanced-patterns/references/decorators.md` |
| Performance Best Practices | `skills/typescript-advanced-patterns/references/performance-best-practices.md` |
| Common Pitfalls | `skills/typescript-advanced-patterns/references/common-pitfalls.md` |
| Testing Types | `skills/typescript-advanced-patterns/references/testing-types.md` |
## Implementation Workflow
### 1. Identify Pattern Need
- Analyze type safety requirements
- Identify runtime vs compile-time constraints
- Choose appropriate pattern from Quick Reference
### 2. Load Reference
- Read specific reference file for pattern
- Review examples and use cases
- Understand trade-offs
### 3. Implement Pattern
- Start simple, add complexity as needed
- Use strict mode (`tsconfig.json` with `"strict": true`)
- Test with type assertions
### 4. Validate
- Ensure type errors caught at compile time
- Verify runtime behavior matches types
- Check performance (avoid excessive type complexity)
### 5. Document
- Add JSDoc comments for public APIs
- Document type constraints and assumptions
- Provide usage examples
## Common Mistakes to Avoid
1. **Using `any` instead of `unknown`**: Loses all type safety
- Use `unknown` and type guards instead
2. **Type assertions without validation**: Unsafe runtime behavior
- Prefer type guards (`value is Type`) over `as Type`
3. **Overusing generics**: Unnecessary complexity
- Only use generics when types truly vary
4. **Deep type nesting**: Slow compilation, hard to debug
- Keep types composable and shallow
5. **Forgetting `readonly`**: Accidental mutations
- Mark immutable data structures as `readonly`
6. **Not enabling strict mode**: Missing null checks and type errors
- Always use `"strict": true` in `tsconfig.json`
7. **Mixing type and interface incorrectly**: Confusing semantics
- Use `type` for unions/utilities, `interface` for object shapes
## Quick Patterns
### Type-Safe ID
```typescript
type UserId = string & { readonly __brand: 'UserId' };
function createUserId(id: string): UserId { return id as UserId; }
```
### Discriminated Union
```typescript
type State =
| { status: 'loading' }
| { status: 'success'; data: string }
| { status: 'error'; error: Error };
```
### Mapped Type Transformation
```typescript
type Readonly<T> = { readonly [P in keyof T]: T[P] };
type Partial<T> = { [P in keyof T]?: T[P] };
```
### Type Guard
```typescript
function isString(value: unknown): value is string {
return typeof value === 'string';
}
```
## Resources
- **TypeScript Handbook**: https://www.typescriptlang.org/docs/handbook/
- **Type Challenges**: https://github.com/type-challenges/type-challenges
- **ts-toolbelt**: Advanced type utilities library
- **zod**: Runtime validation with TypeScript inference
- **tsd**: Test TypeScript type definitions