TypeScript Academy · Lesson

Type-Level Comparisons

Compare numbers entirely at the type level.

Lesson 3 of 413 steps

Type-Level Comparisons is a free TypeScript Academy lesson on CoddyKit. This is 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, and your progress syncs across the web and the CoddyKit app. The TypeScript Academy course includes 4 lessons in total.

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.

Free to start

Learn TypeScript with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
101
Lessons
352

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. 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. The TypeScript Academy course includes 4 lessons in total.

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, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.

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