这篇文章将为大家详细讲解有关TypeScript中怎么实现一个斐波那契数列,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
成都一家集口碑和实力的网站建设服务商,拥有专业的企业建站团队和靠谱的建站技术,十年企业及个人网站建设经验 ,为成都上1000家客户提供网页设计制作,网站开发,企业网站制作建设等服务,包括成都营销型网站建设,品牌网站制作,同时也为不同行业的客户提供做网站、成都做网站的服务,包括成都电商型网站制作建设,装修行业网站制作建设,传统机械行业网站建设,传统农业行业网站制作建设。在成都做网站,选网站制作建设服务商就选成都创新互联。
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)); }
运行结果如下:
斐波那契数列打印结果
程序完全没问题,完结撒花!
开玩笑的,上面是只一个用了TypeScript类型定义的JavaScript写法,我们其实真正想这样做↓↓↓, 也就是使用TS Type解决FIbonacci
import { Fib, Add } from './fib-type'; type one = Fib<1>; type zero = Fib<0>; type Two = Add; type Five = Add >; type Fib5 = Fib ; type Fib9 = Fib<9>; type r0 = Fib ; // type r0= 0 type r1 = Fib ; // type r1 = 1 type r2 = Fib ; // 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 type r9 = Fib<9>; // type r9 = 34 type sum = Add ; // type sum = 42
类型提示
要想实现斐波那契数列,参考一开始的代码,有基本的比较, 加法, 循环语法, 所以我们也需要使用类型系统依次实现这三种功能
为了实现加法, 需要先实现一些工具类型
// 元组长度 type Length= T['length']; type one = 1 // 使用extends实现数字相等的比较 type a111 = 0 extends one ? true : false // type a111 = false type a112 = 1 extends one ? true : false // type a112 = true
range的实现是递归实现的
// 伪代码 function range(n, list=[]){ if(n<=0) return list.length return range(n-1, [1, ...list]) }
TypeScript的限制, 没有循环, 只能用递归代替循环, 后面会有几个类似的写法, 记住一点:递归有几个出口, 对象就有几个 key, 每个 key 就是一个条件
// 创建指定长度的元组, 用第二个参数携带返回值 type Range= { 0: Range ; 1: P; }[Length extends T ? 1 : 0]; // 拼接两个元组 type Concat
= [...T, ...P]; type t1 = Range<3>; // type t1 = [any, any, any] type Zero = Length >; // type Zero = 0 type Ten = Length >; // type Ten = 10 type Five = Length >; // type Five = 5 type One = Length >;
有了上面的工具语法,那么实现加法就比较容易了, 只需要求两个元组合并后的长度
type Add= Length< Concat , Range > >; type Two = Add
; // type Two = 2 type Three = Add ; // type Three = 3
有了加法,该如何实现减法呢?一般减法和除法都比加法难, 所以我们需要更多的工具类型函数!
2.2.1 实现一些基本工具类型
Shift:删除第一个元素
Append:在元组末尾插入元素
IsEmpty / NotEmpty:判断列表为空
// 去除元组第一个元素 [1,2,3] -> [2,3] type Shift= ((...t: T) => any) extends ( _: any, ...Shift: infer P ) => any ? P : []; type pp = Shift<[number, boolean,string, Object]> // type pp = [boolean, string, Object] // 向元组中追加 type Append = [...T, E]; type IsEmpty = Length extends 0 ? true : false; type NotEmpty = IsEmpty extends true ? false : true; type t4 = IsEmpty >; // type t4 = true type t5 = IsEmpty >; // type t5 = false
2.2.2 逻辑类型
And:a && b
// 逻辑操作 type And= T extends false ? false : P extends false ? false : true; type t6 = And ; // type t6 = true type t7 = And ; // type t7 = false type t8 = And ; // type t8 = false type t9 = And ; // type t9 = false
2.2.3 小于等于
伪代码: 主要思想是同时从列表中取出一个元素, 长度先到0的列表比较短
function dfs (a, b){ if(a.length && b.length){ a.pop() b.pop() return dfs(a,b) }else if(a.length){ a >= b }else if (b.length){ b > a } }
思想:将数字的比较转换为列表长度的比较
// 元组的小于等于 T <= P, 同时去除一个元素, 长度先到0的比较小 type LessEqList= { 0: LessEqList , Shift >; 1: true; 2: false; }[And
, NotEmpty > extends true ? 0 : IsEmpty
extends true ? 1 : 2]; // 数字的小于等于 type LessEq = LessEqList , Range >; type t10 = LessEq
; // type t10 = true type t11 = LessEq ; // type t11 = false type t12 = LessEq ; // type t12 = true
减法有两个思路,列表长度相减求值和数字相减求值
2.3.1 列表减法
默认大减小, 小减大只需要判断下反着来, 然后加个符号就行了, 这里为了简单没有实现,可参考伪代码如下:
// 伪代码 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.lengthconsole.log(c.length); // 元组的减法 T - P, 同时去除一个元素, 长度到0时, 剩下的就是结果, 这里使用第三个参数来携带结果, 每次做一次减法, 向第三个列表里面追加 type SubList= { 0: Length ; 1: SubList , P, Apped >; }[Length extends Length ? 0 : 1]; type t13 = SubList
, Range<5>>; // type t13 = 5
2.3.2 数字减法
思想:将数字转成元组后再比较
// 集合大小不能为负数, 默认大减小 // 数字的减法 type Sub= { 0: Sub ; 1: SubList
, Range >; }[LessEq
extends true ? 0 : 1]; type t14 = Sub ; // type t14 = 1 type t15 = Sub ; // type t15 = 5
我们有了这些工具后, 就可以将一开始用JavaScript实现的斐波那契数列的实现代码,翻译为TypeScript类型编码
在JavaScript中,我们使用函数
const fib = (n: number): number => n <= 1 ? n : fib(n - 1) + fib(n - 2);
在TypeScript中,我们使用类型, 其实只是换了一种写法, 用类型函数描述运算, 万变不离其宗~
由于TypeScript递归限制, 并不能求解非常大的项, 不过好玩就完事了~
export type Fib= { 0: T; 1: Add >, Fib>>; }[LessEq extends true ? 0 : 1]; type r0 = Fib ; // type r10= 0 type r1 = Fib ; // type r1 = 1 type r2 = Fib ; // 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
关于TypeScript中怎么实现一个斐波那契数列就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。