TRT
Sign in
mediumAdvancedcoding

Explain how to implement Zero-Cost Branded Types in TypeScript, how distributive conditional types and `infer` work (e.g., implementing `Awaited<T>` or.

Write the `Brand<T, B>` phantom symbol intersection, implement recursive `MyAwaited<T>` with `infer U`, and contrast method bivariance with function-property contravariance.

TRT practice prompt — not a verified question from a named employer.

The Runtime Theory Team2 min read

A strong answer

We intersect the primitive type string with a phantom object type keyed by a unique symbol: declare const __brand: unique symbol; type Brand<T, B extends string> = T & { readonly [__brand]: B }; type TenantId = Brand<string, 'TenantId'>;. (1) Compile-Time Nominal Safety: TenantId and OrderId have incompatible literal types at [__brand] ('TenantId' & 'OrderId' == never), so passing an OrderId to a TenantId parameter is a compile error, and raw strings can only become TenantId through a single validating smart constructor (parseTenantId(raw: string): TenantId). (2) Zero Runtime Cost: TypeScript erases type intersections and casts (raw as TenantId) completely—at runtime, a TenantId is just a raw V8 string pointer (0 wrapper bytes!). (3) Variance: Under strictFunctionTypes, producer return types are covariant (out T) while consumer parameter types are contravariant (in T)—except when declared with method shorthand fn(x: T): void (which is bivariant!), so always use property syntax fn: (x: T) => void for strict contravariant checking.

A value of type Brand<T, B> can only be constructed via an explicit smart constructor or type predicate for brand B, is assignable to base type T without unwrapping, and has 0 bytes of runtime memory overhead over T. Because T & { readonly [__brand]: B } is a subtype of T ($T \cap B \subseteq T$) but T is not a subtype of T & { readonly [__brand]: B }, raw unvalidated T values and values with a different brand $B' \ne B$ are rejected by the structural type checker while erasing to plain T in emitted JavaScript.

Phantom Branded Types add 0 bytes of heap memory and 0 ns of CPU overhead after the single boundary smart constructor check, compared to +32 bytes per ID for runtime wrapper classes (new TenantId(s)). In production systems (Prisma, tRPC, Effect-TS (Brand.nominal), Zod .brand<'TenantId'>(), and TypeScript 4.7+ explicit variance annotations (interface Producer<out T>, interface Consumer<in T>).), engineers monitor these exact trade-offs to keep p99 latency predictable and prevent resource exhaustion under peak load.

What the interviewer is listening for

  • Traces how Phantom Branded Types, Distributive Conditional Types (infer), and Covariance vs Contravariance operates in memory step by step rather than giving a vague textbook definition.
  • States the core correctness invariant and explains why edge cases do not violate it.
  • Quantifies time, space, and hardware costs (Phantom Brand (Brand<string, 'UserId'>), Explicit Variance (interface Box<out T>)) with concrete numbers.
  • Identifies real-world failure modes (Writing type IsNever<T> = T extends never ? true : false; and expecting IsNever<never> to be true) and explains how production systems mitigate them.

Common mistakes

  • Treating Phantom Branded Types, Distributive Conditional Types (infer), and Covariance vs Contravariance as a black box without explaining the underlying memory or state transitions.
  • Ignoring worst-case tail latency or memory overhead (Using new Number(x) or wrapper objects to distinguish UsdCents from EurCents).
  • Forgetting boundary conditions and error recovery (Using method syntax validate(input: T): boolean in a generic validator interface).

This answer walks

Practice follow-ups

  1. 01How do you prevent `T extends ...` from returning `any` when `T` itself is `any` or `never`? (Hint: `type IsNever<T> = [T] extends [never] ? true : false`!)
  2. 02Why does `IsNever<never>` evaluate to `never` instead of `true` if you forget the `[T] extends [never]` tuple brackets?

Not started

Sign in to save your learning progress.

Sign in to save