Skip to content

Instantly share code, notes, and snippets.

@bsitruk
Created July 2, 2025 09:26
Show Gist options
  • Save bsitruk/3c57b1d062c950dabdcc9158ca2c4b00 to your computer and use it in GitHub Desktop.
Save bsitruk/3c57b1d062c950dabdcc9158ca2c4b00 to your computer and use it in GitHub Desktop.

TS Lazy Conditional Type Evaluation

Below is a five-line “playground-size” demo that lets you watch the conditional type stay in its unevaluated form inside a generic function and collapse as soon as you call the function with a concrete argument.

// 1 ─ a tiny conditional type
type Kind<T> = T extends string ? "str" : "other";

// 2 ─ generic function: the test type receives a **bare** type parameter
function lazy<T>(value: T) {
  type Inside = Kind<T>;          // 3: Inside is still  Kind<T>
  return null as unknown as Inside;
}

// 4 ─ call sites supply concrete types, so the compiler finally reduces it
const a = lazy("hello");   // a: "str"
const b = lazy(123);       // b: "other"
  • Line 3 (inside lazy) T is a bare type parameter, so the compiler postpones the test T extends string ? … : …. Hover in an editor and you’ll see Inside reported literally as Kind<T>—the conditional hasn’t run yet.

  • Lines 4 – 5 (outside lazy) Each call substitutes a concrete type (string or number) for T. Now the condition can be decided, so Kind<string> reduces to "str" and Kind<number> to "other".

That postponement is exactly what TypeScript’s documentation refers to as “deferred” or “lazy” evaluation of conditional types involving bare type parameters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment