Skip to content

@tank/typescript-generics

1.0.0

Description

Advanced TypeScript generics covering constraints, conditional and mapped types, template literal types, infer, utility types, branded types, discriminated unions, variance, and real-world generic patterns.

Triggered by

TypeScript genericsconditional typemapped typeinferutility typesbranded type
Download
Verified
tank install @tank/typescript-generics

TypeScript Generics

Core Philosophy

  1. Generics are functions for types -- A generic parameter is a type-level variable. Pass types in, get types out. Think of <T> as the same kind of abstraction as (x) in value-level code.
  2. Constrain early, infer often -- Apply the tightest constraint that satisfies the use case via extends. Let TypeScript infer the rest. Explicit type arguments are a code smell when inference works.
  3. Prefer composition over recursion -- Compose built-in utility types and simple conditionals. Recursive types hit the 50-depth limit and destroy IDE performance.
  4. Types should disappear at runtime -- The best generic code compiles to the same JavaScript as hand-written code. If generics force runtime checks, redesign the type.
  5. Read the error from the bottom -- TypeScript error messages for generics are deeply nested. The actual constraint violation is at the bottom of the stack.

Quick-Start: Common Problems

"I need a function that works on multiple types"

  1. Add a type parameter: function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>
  2. Constrain with extends -- use keyof, interfaces, or unions
  3. Let inference fill in T from the call site argument -> See references/generics-fundamentals.md

"Which utility type do I need?"

GoalUtility
Make all props optionalPartial<T>
Make all props requiredRequired<T>
Select subset of propsPick<T, K>
Remove specific propsOmit<T, K>
Object from key-value unionRecord<K, V>
Remove members from unionExclude<U, M>
Keep members from unionExtract<U, M>
Function return typeReturnType<F>
Function parameter typesParameters<F>
Unwrap PromiseAwaited<T>
-> See references/utility-types.md

"My conditional type doesn't distribute correctly"

  1. Wrap both sides in [T] extends [U] to disable distribution
  2. Use never to filter union members: T extends U ? T : never
  3. Remember: distribution only happens on naked type parameters -> See references/conditional-types.md

"Type instantiation is excessively deep"

  1. Reduce recursive depth -- flatten with tail-call patterns or iterative mapped types
  2. Add explicit type annotations at intermediate steps
  3. Break complex types into smaller named aliases
  4. Use NoInfer<T> (TS 5.4+) to block unwanted inference sites -> See references/errors-performance.md

"I want types that prevent invalid states"

  1. Use discriminated unions with a literal kind/type tag
  2. Add branded types for domain primitives (UserId, Email)
  3. Model state machines as discriminated unions -> See references/branded-discriminated.md

Decision Trees

Generic vs Overload vs Union

SignalApproach
Return type depends on input typeGeneric
Few fixed input-output pairsOverloads
Accept several types, same returnUnion parameter
Need to relate multiple paramsGeneric with multiple type params

Mapped vs Conditional vs Template Literal

NeedType Feature
Transform every property of an objectMapped type
Branch on a type conditionConditional type
Build string types from partsTemplate literal type
Extract inner type from wrapperinfer in conditional
Remap object keysMapped type with as clause

Constraint Strategy

ScenarioConstraint
Must have specific propertyT extends { prop: Type }
Must be object keyK extends keyof T
Must be callableT extends (...args: any[]) => any
Must be constructableT extends abstract new (...args: any[]) => any
Must be a string subtypeT extends string
Array element type neededT extends readonly any[] then T[number]

Reference Index

FileContents
references/generics-fundamentals.mdType parameters, constraints, defaults, inference, generic functions, classes, and interfaces
references/conditional-types.mdConditional syntax, distributive behavior, infer keyword, never filtering, and non-distributive patterns
references/mapped-types.mdProperty iteration, modifier removal (-readonly, -?), key remapping with as, homomorphic mappings
references/template-literal-types.mdString type construction, union expansion, intrinsic string types, event emitter patterns
references/utility-types.mdAll built-in utility types with implementation, use cases, and composition patterns
references/branded-discriminated.mdBranded/opaque types, discriminated unions, type narrowing, type guards, assertions, satisfies
references/variance-advanced.mdCovariance, contravariance, in/out annotations, generic classes, higher-kinded type emulation
references/real-world-patterns.mdBuilder pattern, factory, registry, type-safe event emitter, state machine, Zod/tRPC patterns
references/errors-performance.mdCommon error messages, recursive type limits, performance tuning, NoInfer, debugging strategies

Command Palette

Search skills, docs, and navigate Tank