TypeScript Type-Level Programming: Compute Fibonacci with Types

This article explores how to implement the Fibonacci sequence using TypeScript's type system, turning type declarations into compile‑time calculations by building utility types for arithmetic, comparisons, and recursion, and demonstrates the full type‑level solution alongside a JavaScript reference.

ELab Team
ELab Team
ELab Team
TypeScript Type-Level Programming: Compute Fibonacci with Types

What We Want to Do

We aim to implement the Fibonacci sequence using TypeScript's type-level syntax, turning type declarations into a programmable computation.

Reference JavaScript Implementation

const fib = (n: number): number => n <= 1 ? n : fib(n - 1) + fib(n - 2);
for (let i = 0; i < 10; i++) {
  console.log(i, fib(i));
}

Running this prints the first ten Fibonacci numbers.

Fibonacci output
Fibonacci output

Type-Level Implementation

Using type definitions we can express the same computation.

import { Fib, Add } from './fib-type';

type one = Fib<1>;
type zero = Fib<0>;

type Two = Add<one, one>;
type Five = Add<Two, Add<Two, one>>;

type Fib5 = Fib<Five>;
type Fib9 = Fib<9>;

type r0 = Fib<Zero>; // 0
type r1 = Fib<One>; // 1
type r2 = Fib<Two>; // 1
type r3 = Fib<3>; // 2
type r4 = Fib<4>; // 3
type r5 = Fib<5>; // 5
type r6 = Fib<6>; // 8
Type-level Fibonacci
Type-level Fibonacci

Building Blocks

To perform arithmetic at the type level we define utility types such as Length, Shift, Append, IsEmpty, NotEmpty, And, Range, Concat, LessEq, SubList, Sub, and finally Fib.

type Length<T extends any[]> = T['length'];

type Shift<T extends any[]> = ((...t: T) => any) extends (_: any, ...Shift: infer P) => any ? P : [];

type Append<T extends any[], E = any> = [...T, E];

type IsEmpty<T extends any[]> = Length<T> extends 0 ? true : false;

type NotEmpty<T extends any[]> = IsEmpty<T> extends true ? false : true;

type And<T extends boolean, P extends boolean> = T extends false ? false : P extends false ? false : true;

type Range<T extends number, P extends any[] = []> = {0: Range<T, [any, ...P]>;1: P}[Length<P> extends T ? 0 : 1];

type Concat<T extends any[], P extends any[]> = [...T, ...P];

type LessEqList<T extends any[], P extends any[]> = {
  0: LessEqList<Shift<T>, Shift<P>>;
  1: true;
  2: false;
}[And<NotEmpty<T>, NotEmpty<P>> extends true ? 0 : IsEmpty<T> extends true ? 1 : 2];

type LessEq<T extends number, P extends number> = LessEqList<Range<T>, Range<P>>;

type Add<T extends number, P extends number> = Length<Concat<Range<T>, Range<P>>>;

type SubList<T extends any[], P extends any[], R extends any[] = []> = {
  0: Length<R>;
  1: SubList<Shift<T>, P, Append<R, any>>;
}[Length<T> extends Length<P> ? 0 : 1];

type Sub<T extends number, P extends number> = {
  0: Sub<P, T>;
  1: SubList<Range<T>, Range<P>>;
}[LessEq<T, P> extends true ? 0 : 1];

export type Fib<T extends number> = {
  0: T;
  1: Add<Fib<Sub<T, One>>, Fib<Sub<T, Two>>>;
}[LessEq<T, One> extends true ? 0 : 1];

Conclusion

The article demonstrates how TypeScript's type system can be used to perform compile‑time calculations such as the Fibonacci sequence, offering a playful exploration of type‑level programming.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

TypeScriptFibonaccitype-level programmingcompile-time computationtype recursion
ELab Team
Written by

ELab Team

Sharing fresh technical insights

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.