日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
用TypeScript類型系統(tǒng)編程實(shí)現(xiàn)斐波那契數(shù)列

本文轉(zhuǎn)載自微信公眾號「DYBOY」,作者DYBOY。轉(zhuǎn)載本文請聯(lián)系DYBOY公眾號。

創(chuàng)新互聯(lián)于2013年開始,先為定日等服務(wù)建站,定日等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為定日企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

作為一名前端開發(fā)者,一定知道TypeScript經(jīng)常被用于項(xiàng)目中的類型約束,使得在JavaScript這種弱類型語言中有了靜態(tài)檢查的能力,也推進(jìn)了前端工程化的演進(jìn)速度,在研究學(xué)習(xí)TypeScript過程中,我的小伙伴發(fā)現(xiàn)了TS的一些好玩兒功能,獨(dú)樂樂不容眾樂樂,遂分享這篇文章給大家。

小伙伴(育豪)的原文可能理解起來有一些難度,筆者有嘗試增加一些描述,但想要完全領(lǐng)略TS的“類型體操”的奧妙,還是得實(shí)操一番。

一、我們要做什么

我們的目的是想要通過TypeScript的類型聲明式語法,編程實(shí)現(xiàn)一個(gè)斐波那契數(shù)列算法。換句話說,類似于用現(xiàn)有的機(jī)器碼到指令集、二進(jìn)制到十進(jìn)制、匯編語言到高級編程語言的過程,讓類型定義語法也可以實(shí)現(xiàn)編程。

最終我們要實(shí)現(xiàn)的斐波那契數(shù)列代碼是這樣的?

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

運(yùn)行結(jié)果如下:

斐波那契數(shù)列打印結(jié)果

程序完全沒問題,完結(jié)撒花!

開玩笑的,上面是只一個(gè)用了TypeScript類型定義的JavaScript寫法,我們其實(shí)真正想這樣做↓↓↓, 也就是使用TS Type解決FIbonacci

 
 
 
 
  1. import { Fib, Add } from './fib-type'; 
  2.  
  3. type one = Fib<1>; 
  4. type zero = Fib<0>; 
  5. type Two = Add
  6. type Five = Add>; 
  7. type Fib5 = Fib
  8. type Fib9 = Fib<9>; 
  9. type r0 = Fib; // type r0= 0 
  10. type r1 = Fib; // type r1 = 1 
  11. type r2 = Fib; // type r2 = 1 
  12. type r3 = Fib<3>; // type r3 = 2 
  13. type r4 = Fib<4>; // type r4 = 3 
  14. type r5 = Fib<5>; // type r5 = 5 
  15. type r6 = Fib<6>; // type r6 = 8 
  16. type r9 = Fib<9>; // type r9 = 34 
  17. type sum = Add; // type sum = 42 

類型提示

二、我們該怎么做

要想實(shí)現(xiàn)斐波那契數(shù)列,參考一開始的代碼,有基本的比較, 加法, 循環(huán)語法, 所以我們也需要使用類型系統(tǒng)依次實(shí)現(xiàn)這三種功能

2.1 加法的實(shí)現(xiàn)

為了實(shí)現(xiàn)加法, 需要先實(shí)現(xiàn)一些工具類型

 
 
 
 
  1. // 元組長度 
  2. type Length = T['length']; 
  3. type one = 1  
  4.  
  5. // 使用extends實(shí)現(xiàn)數(shù)字相等的比較 
  6. type a111 = 0 extends one ? true : false // type a111 = false 
  7. type a112 = 1 extends one ? true : false // type a112 = true 

range的實(shí)現(xiàn)是遞歸實(shí)現(xiàn)的

 
 
 
 
  1. // 偽代碼 
  2. function range(n, list=[]){ 
  3.   if(n<=0) return list.length 
  4.   return range(n-1, [1, ...list]) 

TypeScript的限制, 沒有循環(huán), 只能用遞歸代替循環(huán), 后面會有幾個(gè)類似的寫法, 記住一點(diǎn):遞歸有幾個(gè)出口, 對象就有幾個(gè) key, 每個(gè) key 就是一個(gè)條件

 
 
 
 
  1. // 創(chuàng)建指定長度的元組, 用第二個(gè)參數(shù)攜帶返回值 
  2. type Range = { 
  3.   0: Range
  4.   1: P; 
  5. }[Length

     extends T ? 1 : 0]; 

  6.  
  7. // 拼接兩個(gè)元組 
  8. type Concat = [...T, ...P]; 
  9.  
  10. type t1 = Range<3>; 
  11. // type t1 = [any, any, any] 
  12.  
  13. type Zero = Length>; 
  14. //   type Zero = 0 
  15. type Ten = Length>; 
  16. // type Ten = 10 
  17.  
  18. type Five = Length>; 
  19. // type Five = 5 
  20.  
  21. type One = Length>; 

有了上面的工具語法,那么實(shí)現(xiàn)加法就比較容易了, 只需要求兩個(gè)元組合并后的長度

 
 
 
 
  1. type Add = Length< 
  2.    Concat, Range

  3.  >; 
  4.  type Two = Add
  5.  //   type Two = 2 
  6.  type Three = Add
  7.  // type Three = 3 

有了加法,該如何實(shí)現(xiàn)減法呢?一般減法和除法都比加法難, 所以我們需要更多的工具類型函數(shù)!

2.2 工具函數(shù)

2.2.1 實(shí)現(xiàn)一些基本工具類型

  • Shift:刪除第一個(gè)元素
  • Append:在元組末尾插入元素
  • IsEmpty / NotEmpty:判斷列表為空
 
 
 
 
  1. // 去除元組第一個(gè)元素 [1,2,3] -> [2,3] 
  2. type Shift = ((...t: T) => any) extends ( 
  3.   _: any, 
  4.   ...Shift: infer P 
  5. ) => any 
  6.   ? P 
  7.   : []; 
  8.  
  9. type pp = Shift<[number, boolean,string, Object]> 
  10. // type pp = [boolean, string, Object] 
  11.  
  12. // 向元組中追加 
  13. type Append = [...T, E]; 
  14. type IsEmpty = Length extends 0 ? true : false; 
  15. type NotEmpty = IsEmpty extends true ? false : true; 
  16. type t4 = IsEmpty>; 
  17. // type t4 = true 
  18.  
  19. type t5 = IsEmpty>; 
  20. // type t5 = false 

2.2.2 邏輯類型

  • And:a && b
 
 
 
 
  1. // 邏輯操作 
  2. type And = T extends false 
  3.   ? false 
  4.   : P extends false 
  5.   ? false 
  6.   : true; 
  7. type t6 = And
  8. // type t6 = true 
  9.  
  10. type t7 = And
  11. // type t7 = false 
  12.  
  13. type t8 = And
  14. // type t8 = false 
  15.  
  16. type t9 = And
  17. // type t9 = false 

2.2.3 小于等于

偽代碼: 主要思想是同時(shí)從列表中取出一個(gè)元素, 長度先到0的列表比較短

 
 
 
 
  1. function dfs (a, b){ 
  2.     if(a.length && b.length){ 
  3.         a.pop() 
  4.         b.pop() 
  5.         return dfs(a,b) 
  6.     }else if(a.length){ 
  7.         a >= b 
  8.     }else if (b.length){ 
  9.         b > a 
  10.     } 

思想:將數(shù)字的比較轉(zhuǎn)換為列表長度的比較

 
 
 
 
  1. // 元組的小于等于   T <= P, 同時(shí)去除一個(gè)元素, 長度先到0的比較小 
  2. type LessEqList = { 
  3.   0: LessEqList, Shift

    >; 

  4.   1: true; 
  5.   2: false; 
  6. }[And, NotEmpty

    > extends true 

  7.   ? 0 
  8.   : IsEmpty extends true 
  9.   ? 1 
  10.   : 2]; 
  11.  
  12.  
  13. // 數(shù)字的小于等于 
  14. type LessEq = LessEqList, Range

    >; 

  15.  
  16. type t10 = LessEq
  17. // type t10 = true 
  18. type t11 = LessEq
  19. // type t11 = false 
  20.  
  21. type t12 = LessEq
  22. // type t12 = true 

2.3 減法的實(shí)現(xiàn)

減法有兩個(gè)思路,列表長度相減求值和數(shù)字相減求值

2.3.1 列表減法

默認(rèn)大減小, 小減大只需要判斷下反著來, 然后加個(gè)符號就行了, 這里為了簡單沒有實(shí)現(xiàn),可參考偽代碼如下:

 
 
 
 
  1. // 偽代碼 
  2. const a = [1, 2, 3]; 
  3. const b = [4, 5]; 
  4. const c = []; 
  5. while (b.length !== a.length) { 
  6.   a.pop(); 
  7.   c.push(1); 
  8. }// c.length === a.length - b.lengthconsole.log(c.length); 
  9.  
  10. // 元組的減法 T - P, 同時(shí)去除一個(gè)元素, 長度到0時(shí), 剩下的就是結(jié)果, 這里使用第三個(gè)參數(shù)來攜帶結(jié)果, 每次做一次減法, 向第三個(gè)列表里面追加 
  11. type SubList = { 
  12.   0: Length
  13.   1: SubList, P, Apped>; 
  14. }[Length extends Length

     ? 0 : 1]; 

  15. type t13 = SubList, Range<5>>; 
  16. // type t13 = 5 

2.3.2 數(shù)字減法

思想:將數(shù)字轉(zhuǎn)成元組后再比較

 
 
 
 
  1. // 集合大小不能為負(fù)數(shù), 默認(rèn)大減小 
  2. // 數(shù)字的減法 
  3. type Sub = { 
  4.   0: Sub
  5.   1: SubList, Range

    >; 

  6. }[LessEq extends true ? 0 : 1]; 
  7.  
  8. type t14 = Sub
  9. //   type t14 = 1 
  10. type t15 = Sub
  11. // type t15 = 5 

我們有了這些工具后, 就可以將一開始用JavaScript實(shí)現(xiàn)的斐波那契數(shù)列的實(shí)現(xiàn)代碼,翻譯為TypeScript類型編碼

三、Fib: JS函數(shù) --> TS類型

在JavaScript中,我們使用函數(shù)

 
 
 
 
  1. const fib = (n: number): number => n <= 1 ? n : fib(n - 1) + fib(n - 2); 

在TypeScript中,我們使用類型, 其實(shí)只是換了一種寫法, 用類型函數(shù)描述運(yùn)算, 萬變不離其宗~

由于TypeScript遞歸限制, 并不能求解非常大的項(xiàng), 不過好玩就完事了~

 
 
 
 
  1. export type Fib = { 
  2.   0: T; 
  3.   1: Add>, Fib>>; 
  4. }[LessEq extends true ? 0 : 1]; 
  5.  
  6. type r0 = Fib
  7. // type r10= 0 
  8. type r1 = Fib
  9. // type r1 = 1 
  10.  
  11. type r2 = Fib
  12. // type r2 = 1 
  13.  
  14. type r3 = Fib<3>; 
  15. // type r3 = 2 
  16.  
  17. type r4 = Fib<4>; 
  18. // type r4 = 3 
  19.  
  20. type r5 = Fib<5>; 
  21. //type r5 = 5 
  22.  
  23. type r6 = Fib<6>; 
  24. //   type r6 = 8 

最后,推薦一些其他好玩的項(xiàng)目:

  • 《TypeScript類型元編程:實(shí)現(xiàn)8位數(shù)的算術(shù)運(yùn)算》 - https://zhuanlan.zhihu.com/p/85655537
  • 《TypeScript 4.1 新特性:字符串模板類型,Vuex 終于有救了?》 - https://juejin.cn/post/6867785919693832200
  • 《Ts 類型系統(tǒng)實(shí)現(xiàn)線性查找》 - https://bytedance.feishu.cn/docs/doccney0oWRZMSM1w9e0izshW5d

四、總結(jié)

看了TypeScript實(shí)現(xiàn)斐波納切數(shù)列這一套操作有沒有讓你有體驗(yàn)到重回“實(shí)現(xiàn)流水線CPU”的實(shí)驗(yàn)室時(shí)光?

IT在最近幾十年的發(fā)展突飛猛進(jìn),越來越多的“程序員”加入到了互聯(lián)網(wǎng)行業(yè),在一些高級語言以及開發(fā)框架下,“程序員”的編碼也只需要關(guān)注業(yè)務(wù)邏輯實(shí)現(xiàn),很少有人會再去關(guān)注計(jì)算機(jī)底層是怎么實(shí)現(xiàn)加減乘除的,當(dāng)然社會在進(jìn)步,技術(shù)也在日新月異地迭代,偶爾駐足,回憶剛接觸計(jì)算機(jī)編程,在命令行輸出第一行“Hello World!”代碼那時(shí)欣喜的自己,也許那是我們都回不去的青春...


文章標(biāo)題:用TypeScript類型系統(tǒng)編程實(shí)現(xiàn)斐波那契數(shù)列
網(wǎng)頁URL:http://www.5511xx.com/article/ccdohpg.html