0Pricing
TypeScript Academy · Lesson

Type-Level Comparisons

Compare numbers entirely at the type level.

Type-Level Comparisons is a free TypeScript Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Comparing Numbers

To compare numeric literal types you again lean on tuples. The idea: shrink both numbers in lockstep and see which hits zero first. Whichever reaches the empty tuple first is the smaller number.

type BuildTuple<N extends number, Acc extends unknown[] = []> =
  Acc["length"] extends N ? Acc : BuildTuple<N, [...Acc, unknown]>;

Equality of Literals

Numeric literal equality uses mutual assignability. Two literals are equal when each extends the other. Wrapping in tuples avoids union surprises.

type NumEquals<A extends number, B extends number> =
  [A] extends [B] ? ([B] extends [A] ? true : false) : false;

type X = NumEquals<3, 3>; // true
type Y = NumEquals<3, 4>; // false

Greater Than by Shrinking

For A > B, build tuples for both and remove one element from each per step. If B empties first while A still has elements, then A is larger.

type GreaterThan<A extends number, B extends number> =
  BuildTuple<A> extends [...BuildTuple<B>, unknown, ...unknown[]]
    ? true : false;

type X = GreaterThan<5, 3>; // true
type Y = GreaterThan<3, 5>; // false

How the Pattern Reads

The pattern [...BuildTuple<B>, unknown, ...unknown[]] means: a prefix of length B, then at least one more element. If A fits that, A has more elements than B, so A > B.

type A = GreaterThan<4, 4>; // false (no extra element)
type B = GreaterThan<6, 2>; // true

Less Than

LessThan is just GreaterThan with the arguments flipped. Reuse rather than re-derive.

type LessThan<A extends number, B extends number> =
  GreaterThan<B, A>;

type X = LessThan<3, 5>; // true
type Y = LessThan<5, 3>; // false

Greater or Equal

Combine comparison with equality. A >= B is true when A > B or A == B.

type Gte<A extends number, B extends number> =
  GreaterThan<A, B> extends true
    ? true
    : NumEquals<A, B>;

type X = Gte<5, 5>; // true
type Y = Gte<3, 5>; // false

Recursive Comparison

An alternative compares by decrementing both until one reaches zero. This shows the lockstep idea explicitly: whoever hits zero first is smaller.

type Cmp<A extends number, B extends number> =
  A extends 0
    ? (B extends 0 ? "eq" : "lt")
    : B extends 0
      ? "gt"
      : Cmp<Dec<A>, Dec<B>>;

type X = Cmp<3, 5>; // "lt"

The Dec Dependency

The recursive version needs Dec from the previous lesson. Each step removes one mark from each side. When both are zero they are equal; if only one is zero, the other is greater.

type Dec<N extends number> =
  BuildTuple<N> extends [unknown, ...infer R] ? R["length"] : 0;

Equality vs Assignability

Be careful: number extends number is true, but that is not literal equality. Comparisons here assume specific literal types like 3 and 5, not the wide number type.

type A = NumEquals<3, 3>;          // true
type B = 3 extends number ? 1 : 0; // 1 (assignability, not equality)

Building a Sort Key

With comparison you can encode ordering rules. For example, decide at the type level whether a tuple of two numbers is sorted ascending.

type IsSorted<A extends number, B extends number> =
  GreaterThan<A, B> extends true ? false : true;

type X = IsSorted<2, 5>; // true
type Y = IsSorted<5, 2>; // false

Use Sparingly

Comparisons cost recursion. They are great for guarding small bounded values (indices, fixed limits) but are not a general numeric library. Keep operands small and prefer the prefix-pattern form, which is shallower than full lockstep recursion.

type A = GreaterThan<9, 4>; // true (cheap, prefix pattern)

Quick Check

Test your understanding of type-level comparisons.

Recap

You can now order numbers in the type system.

  • Equality via mutual assignability of literals.
  • GreaterThan via a B-length prefix plus an extra element.
  • LessThan flips the arguments; Gte adds equality.
  • Works on small literal numbers, not the wide number type.

Next: turning all this into practical utilities.

Frequently asked questions

Is the “Type-Level Comparisons” lesson free?

Yes — the full text of “Type-Level Comparisons” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Type-Level Comparisons”?

Compare numbers entirely at the type level. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Type-Level Comparisons” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Counting with Tuple Length
  2. Type-Level Addition and Subtraction
  3. Type-Level Comparisons
  4. Practical Numeric Type Utilities
← Back to TypeScript Academy