<!-- llms-explorer concept facts · https://llms-explorer.com/tree/typescript-advanced-types/ · pack 2026-09-08 · ~4856 tokens -->

# TypeScript Advanced Types

> Expert reference for TypeScript's advanced type system. Covers conditional types, mapped types, branded/nominal types, type narrowing, generic constraints, variadic tuples, template literal types, uti

Parent: [TypeScript Expert](https://llms-explorer.com/tree/typescript-expert/) · 28 facets · 79 facts · page: https://llms-explorer.com/tree/typescript-advanced-types/

## TypeScript Advanced Types

- Expert reference for TypeScript's advanced type system. Covers conditional types, mapped types, branded/nominal types, type narrowing, generic constraints, variadic tuples, template literal types, utility type internals, and type-level performance. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#typescript-advanced-types`

## When to use this skill

- Writing or reviewing generic type definitions, conditional types, or mapped types — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-to-use-this-skill`
- Implementing branded/nominal types for domain safety — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-to-use-this-skill`
- Debugging "Type instantiation is excessively deep" or union explosion errors — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-to-use-this-skill`
- Designing type-safe builder patterns, event emitters, or state machines — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-to-use-this-skill`
- Choosing between satisfies, type annotations, and type assertions — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-to-use-this-skill`
- Optimizing slow type checking in large codebases — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-to-use-this-skill`

## When NOT to use this skill

- General TypeScript project setup, tsconfig, module resolution -- use typescript-expert — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-not-to-use-this-skill`
- Runtime validation with Zod/io-ts -- use zod-schema-validation — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-not-to-use-this-skill`
- Framework-specific typing (React, Express, etc.) -- use the framework skill — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-not-to-use-this-skill`
- Pure JavaScript without TypeScript types — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#when-not-to-use-this-skill`

## Scope boundary

- This skill covers the TYPE SYSTEM exclusively. For general TypeScript project setup, runtime patterns, module resolution, or framework integration, use the typescript-expert skill instead. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#scope-boundary`

## Distributive conditional types

- When the checked type is a naked type parameter, the conditional distributes over union members individually. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#distributive-conditional-types`
- Preventing distribution -- wrap both sides in a tuple: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#distributive-conditional-types`

## The `infer` keyword

- Extract types from within structural positions: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#the-infer-keyword`

## `infer` with constraints (TS 4.7+)

- Constrain the inferred type inline: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#infer-with-constraints-ts-47`

## Key remapping with `as` (TS 4.1+)

- Rename, prefix, or filter keys during iteration: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#key-remapping-with-as-ts-41`

## Filtering keys with `as` + `never`

- Returning never from the as clause removes the key: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#filtering-keys-with-as-never`

## Homomorphic mapped types

- A mapped type { [P in keyof T]: ... } is homomorphic -- it preserves the property modifiers (readonly, optional) of the source type T. This is what makes Readonly<T> and Partial<T> work correctly. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#homomorphic-mapped-types`
- Key fact (a common myth, corrected): the compiler keys homomorphism on the in keyof T constraint, not on the presence of an as clause. Adding as does not by itself break homomorphism -- modifiers are still copied for every key that survives the remap. Only keys whose identity changes (e.g. remapped to a template-literal string) lose 1:1 modifier provenance, because the output key differs from the source key. So { [K in keyof T as F<K>]: ... } remains modifier-homomorphic over its surviving keys. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#homomorphic-mapped-types`

## 3. Branded / Nominal Types

- TypeScript uses structural typing. Branded types simulate nominal typing by adding a phantom property that makes structurally identical types incompatible. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#3-branded-nominal-types`

## Pattern 2: Unique symbol brand (library-safe)

- Unique symbols guarantee the brand key is truly unique, even across modules: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#pattern-2-unique-symbol-brand-library-safe`

## Pattern 3: Flavor (weaker brand)

- Flavored types accept unbranded values but reject differently-flavored ones: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#pattern-3-flavor-weaker-brand`
- Brand vs Flavor decision: Use Brand when all values MUST go through a factory/validator. Use Flavor when you want softer guardrails that still catch cross-domain mistakes. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#pattern-3-flavor-weaker-brand`

## Assertion functions (TS 3.7+)

- Assertion functions narrow the type for all subsequent code in the same scope: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#assertion-functions-ts-37`

## The `satisfies` operator (TS 4.9+)

- satisfies validates a value against a type WITHOUT widening the inferred type: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#the-satisfies-operator-ts-49`
- When to use satisfies: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#the-satisfies-operator-ts-49`
  - Config objects where you want validation + precise autocomplete — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#the-satisfies-operator-ts-49`
  - Discriminated union values where the discriminant literal must be preserved — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#the-satisfies-operator-ts-49`
  - as const objects that must conform to a schema — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#the-satisfies-operator-ts-49`

## `const` type parameters (TS 5.0+)

- Infer literal types by default instead of widened types: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#const-type-parameters-ts-50`

## Constraint pattern: `readonly unknown[] | []`

- The [] in the union forces tuple inference for array literals instead of widening to arrays: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#constraint-pattern-readonly-unknown-`

## Performance warning

- Template literal types create combinatorial unions. Interpolating two unions of size M and N produces M x N members. Keep interpolated unions under ~10 members each to avoid compiler slowdowns. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#performance-warning`

## `NoInfer<T>` (TS 5.4+)

- Blocks TypeScript from using a position for type inference: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#noinfert-ts-54`
- Use cases for NoInfer: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#noinfert-ts-54`
  - Preventing default parameters from influencing generic inference — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#noinfert-ts-54`
  - Ensuring one argument "drives" the generic while others are checked against it — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#noinfert-ts-54`
  - API design where inference direction matters — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#noinfert-ts-54`

## `Awaited<T>` (TS 4.5+)

- Recursively unwraps Promise types: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#awaitedt-ts-45`

## Avoid deep instantiation

- Deeply nested generics are the primary cause of slow type checking. The compiler has hard limits: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#avoid-deep-instantiation`
  - Type instantiation depth: 50 levels (error: "Type instantiation is excessively deep and possibly infinite") — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#avoid-deep-instantiation`
  - Type instantiation count: 5,000,000 total instantiations — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#avoid-deep-instantiation`
  - Union constituent limit: 100,000 members — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#avoid-deep-instantiation`

## Tail-call optimization for recursive types

- TypeScript recognizes tail-position recursive type aliases and can handle deeper recursion: — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#tail-call-optimization-for-recursive-types`

## Practical performance guidelines

- Flatten unions early. Large intermediate unions compound in later type operations. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#practical-performance-guidelines`
- Avoid Extract/Exclude on large unions in hot paths -- each distributes over every member. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#practical-performance-guidelines`
- Prefer interface over type for object shapes. Interfaces are cached by name; type aliases are structurally re-evaluated. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#practical-performance-guidelines`
- Use skipLibCheck: true to avoid type-checking node_modules .d.ts files in development. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#practical-performance-guidelines`
- Profile with --generateTrace. Run tsc --generateTrace traceDir and open the trace in chrome://tracing to find expensive types. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#practical-performance-guidelines`
- Keep template literal interpolations small. Two 10-member unions produce 100 variants; three produce 1,000. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#practical-performance-guidelines`
- Use interface extends over intersection & for combining object types -- intersections create anonymous types that are harder for the compiler to cache. — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#practical-performance-guidelines`

## Sources

- TypeScript Handbook: Conditional Types — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- TypeScript Handbook: Mapped Types — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- TypeScript Handbook: Template Literal Types — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- TypeScript Handbook: Narrowing — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- TypeScript Handbook: Utility Types — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- NoInfer: TypeScript 5.4's New Utility Type -- Total TypeScript — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- Branded Types in TypeScript -- shramko.dev — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- What the heck is a homomorphic mapped type? -- Andrea Simone Costa — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- Template literal types in TypeScript -- 2ality — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- Computing with tuple types in TypeScript -- 2ality — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- Conditional types in TypeScript -- 2ality — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`
- TypeScript Performance Optimization 2026 -- DEV Community — source: `https://llms-explorer.com/sources/mdb-context-hub/typescript-advanced-types/#sources`

## Where this helps

- Designing a type-safe builder pattern, discriminated union, or state machine and needing to choose between conditional types, mapped types, and generic constraints. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Debugging a "Type instantiation is excessively deep and possibly infinite" error or a slow tsc caused by a specific type construct. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Deciding between satisfies, a type annotation, and a type assertion when validating a config object against a schema. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Implementing domain-safe IDs (branded/nominal types) to stop a UserId and an OrderId - both structurally strings - from being accidentally interchangeable. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*

## Project ideas

- Build a branded-type module for domain identifiers (UserId, OrderId, Email) using the unique symbol brand pattern so IDs from different domains can never be structurally confused. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Build a type-safe event emitter using mapped types and key remapping (as) so event names and payload types stay in sync at compile time. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Build a generic API client where NoInfer<T> forces the response type to be driven by one argument while other arguments are only checked against it, not used for inference. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Write a small conditional-type utility (like a DeepPartial or a recursive Flatten<T>) and use --generateTrace to confirm it doesn't blow past the compiler's instantiation-depth limits. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*

## Antipatterns

- Writing deeply nested recursive generics without checking the compiler's hard limits (50 levels of instantiation depth, 5,000,000 total instantiations) - the classic cause of "excessively deep" errors. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Interpolating two or three large unions inside a template literal type - a 10x10 combination is already 100 variants, and it grows multiplicatively with a third union. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Using type instead of interface for object shapes in hot paths - interfaces are cached by name while type aliases are structurally re-evaluated on every comparison. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Assuming Extract or Exclude are cheap in a hot path over a large union - both distribute over every member, and the cost compounds each time they're used. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*

## Known issues

- The homomorphic-mapped-type behavior (preserving readonly/optional modifiers) is keyed on the `in keyof T` constraint specifically - adding an `as` clause doesn't by itself break it, a detail that's commonly misunderstood. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- satisfies validates a value against a type without widening the inferred type, but it's easy to reach for a plain type annotation instead and lose the precise literal-type autocomplete satisfies was meant to preserve. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Deep instantiation limits (50 levels, 5 million instantiations, 100,000 union members) are hard ceilings, not soft warnings - hitting them means a type genuinely needs restructuring, not just a minor tweak. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
- Performance tuning at the type level (flattening unions early, avoiding intersection &) requires --generateTrace profiling to find the actual hot spot - guessing which type is slow is unreliable. — [source](https://llms-explorer.com/tree/typescript-advanced-types/) *(AI-suggested, synthesized from this pack's existing facts — not extracted from a source document.)*
