DEV Community

阿豪
阿豪

Posted on

How to use TS Type solve Fibonacci

I learned a lot from the post, and this is why I registered account to write my first post.
https://medium.com/free-code-camp/typescript-curry-ramda-types-f747e99744ab

0x00 what we want to do

We want to do like this ↓↓↓ use TS Type solve FIbonacci

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

1x00 How we can do this

1x01 First, we need some util types

They are simple and very easy to understand

  • Range: generate list
  • Length: get list's size
  • Concat: concat two list
 type Length<T extends any[]> = T["length"]; type Range<T extends Number = 0, P extends any[] = []> = { 0: Range<T, [any, ...P]>; 1: P; }[Length<P> extends T ? 1 : 0]; type Concat<T extends any[], P extends any[]> = [...T, ...P]; type t1 = Range<3>; // type t1 = [any, any, any] type Zero = Length<Range<0>>; // type Zero = 0 type One = Length<Range<1>>; // type One = 1 type Ten = Length<Range<10>>; // type Ten = 10 type Five = Length<Range<5>>; // type Five = 5 type Six = Length<Concat<Range<5>, Range<1>>>; // type Six = 6 

Add is also easy

  • We generate two list
  • Concat them
  • Get the result size
 type Add<T extends number, P extends number> = Length< Concat<Range<T>, Range<P>> >; type Two = Add<One, One>; // type Two = 2 type Three = Add<One, Two>; // type Three = 3 

But how to implement subtraction?

1x02 We need more util types

Some array types

  • Append: insert element in head of list
  • IsEmpty/NotEmpty: judge list is/not empty
  • Tail: delete the first element
 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 t4 = IsEmpty<Range<0>>; // type t4 = true type t5 = IsEmpty<Range<1>>; // type t5 = false type Tail<T extends any[]> = ((...t: T) => any) extends ( _: any, ...tail: infer P ) => any ? P : []; type t22 = Tail<[1, 2, 3]>; // type t22 = [2, 3] type t23 = Tail<[1]>; // type t23 = [] type t24 = Tail<[]>; // type t24 = [] 

logic type

  • And: a && b
  • LessList: a.length <= b.length
  • Less: a <= b
 type And<T extends boolean, P extends boolean> = T extends false ? false : P extends false ? false : true; type t6 = And<true, true>; // type t6 = true type t7 = And<true, false>; // type t7 = false type t8 = And<false, false>; // type t8 = false type t9 = And<false, true>; // type t9 = false // T <= P type LessList<T extends any[], P extends any[]> = { 0: LessList<Tail<T>, Tail<P>>; 1: true; 2: false; }[And<NotEmpty<T>, NotEmpty<P>> extends true ? 0 : IsEmpty<T> extends true ? 1 : 2]; type Less<T extends number, P extends number> = LessList<Range<T>, Range<P>>; type t10 = Less<Zero, One>; // type t10 = true type t11 = Less<One, Zero>; // type t11 = false type t12 = Less<One, One>; // type t12 = true 

Now we can 'translate' js to ts

- SubList:

const a = [1, 2, 3]; const b = [4, 5]; const c = []; while (b.length !== a.length) { a.pop(); c.push(1); } // c.length === a.length - b.length console.log(c.length); 
  • Sub: a - b
 type SubList<T extends any[], P extends any[], R extends any[] = []> = { 0: Length<R>; 1: SubList<Tail<T>, P, Append<R>>; }[Length<T> extends Length<P> ? 0 : 1]; type t13 = SubList<Range<10>, Range<5>>; // type t13 = 5 // T - P type Sub<T extends number, P extends number> = { 0: Sub<P, T>; 1: SubList<Range<T>, Range<P>>; }[Less<T, P> extends true ? 0 : 1]; type t14 = Sub<One, Zero>; // type t14 = 1 type t15 = Sub<Ten, Five>; // type t15 = 5 

2x00 JS Function ==> TS Type

In js we use function

const fib = (n) => (n <= 1 ? n : n++); 

in ts we use type!!! they look like same!

 type Fib<T extends number> = { 0: T; 1: Add<Fib<Sub<T, One>>, Fib<Sub<T, Two>>>; }[Less<T, One> extends true ? 0 : 1]; type r0 = Fib<Zero>; // type r10= 0 type r1 = Fib<One>; // type r1 = 1 type r2 = Fib<Two>; // type r2 = 1 type r3 = Fib<3>; // type r3 = 2 type r4 = Fib<4>; // type r4 = 3 type r5 = Fib<5>; //type r5 = 5 type r6 = Fib<6>; // type r6 = 8 

Finally, we use ts solve Fibonacci, This is amazing! I'd never thought of doing that before. Thanks to those who share their genius thoughts 💖~

Top comments (0)