欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

教你用typescript類型來推算斐波那契

 更新時(shí)間:2022年01月23日 15:25:30   作者:字節(jié)跳動(dòng)數(shù)據(jù)平臺前端團(tuán)隊(duì)  
斐波那契是自然界與社會中存在的一種數(shù)學(xué)規(guī)律,下面這篇文章主要給大家介紹了關(guān)于如何用typescript類型來推算斐波那契的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

寫在前面

本文執(zhí)行環(huán)境typescript,版本4.5.4

斐波那契

雖然大家都熟悉斐波那契了,還是簡單的說說吧,一個(gè)知名的數(shù)學(xué)數(shù)列,地推方式如下

  • Fib(0) = 0
  • Fib(1) = 1
  • Fib(n) = Fib(n-1) + Fib(n-2)

最后得出來的數(shù)列就是

0 1 1 2 3 5 8 13 21 34 55 89 ... 

實(shí)現(xiàn)邏輯

介紹完斐波那契后,再來看看typescript類型推算要解決核心點(diǎn)

  • 第0和第1個(gè)數(shù)返回自身
  • 某個(gè)數(shù)等于前兩個(gè)數(shù)相加
  • 推算一個(gè)數(shù)需要循環(huán)或者遞歸得到前兩個(gè)值
  • 輸入的只能是數(shù)字,且不能是負(fù)數(shù)

分析完我們再來看看typescript能夠提供哪些,缺少哪些

第一個(gè)問題:第0和第1個(gè)數(shù)返回自身

這個(gè)滿足,可以通過extends來實(shí)現(xiàn)

type GetSelf<T> = T extends 0 | 1 ? T : never;
// 測試
type Test0 = GetSelf<0>; // 0
type Test1 = GetSelf<1>; // 1
type Test2 = GetSelf<2>; // 2

第二個(gè)問題:某個(gè)數(shù)等于前兩個(gè)數(shù)相加

這個(gè)就開始麻煩了,因?yàn)閠ypesript中是沒有加法運(yùn)算的,也就是說 1 + 2 =  的結(jié)果typescript并不知道,所以列一個(gè)todo

第三個(gè)問題:推算一個(gè)數(shù)需要循環(huán)或者遞歸得到前兩個(gè)值

看看typescript中有沒有遞歸呢,是有的,比如實(shí)現(xiàn)一個(gè)鏈表

type Node<T> = {
    val: T;
    next: Node<T>;
}

不過怎么跳出循環(huán),另外我們需要的是一個(gè)值,而不是返回一個(gè)對象,再列一個(gè)todo

第四個(gè)問題

    輸入的只能是數(shù)字,且不能是負(fù)數(shù)

限定數(shù)字很好做,extends number就可以判斷了,判斷負(fù)數(shù)呢?

    負(fù)數(shù)和正數(shù)有啥區(qū)別呢?

負(fù)數(shù)多個(gè)符號顯示,那改造成字符串后的長度和正數(shù)不等是吧,嘗試

type len1 = '123'['length']; // number
type len2 = number[]['length']; // number;
type len3 = [1, 2, 3]['length']; // 3
type len4 = [number, string]['length']; // 3

字符串和未定義的數(shù)組的長度竟然無法推算,看起來只有元組是可以的

負(fù)數(shù)比0小,可是typescript中沒有比較大小的操作,再列一個(gè)todo

結(jié)論

我們可以解決第一個(gè)問題,同時(shí)得知可以通過 length 來獲取元祖長度,todo如下

  • 加法運(yùn)算
  • 循環(huán)或者遞歸計(jì)算,并有跳出條件
  • 判斷非負(fù)數(shù)

解決todo

+1操作

雖然上一輪大部分功能沒有推算出來,但是得到一個(gè)有用的結(jié)論,元祖是可以得到length的值。

那 +1操作 是不是可以理解成 PUSH操作 后拿出 length 了?嘗試

type Push<T extends Array<number>, P extends number> = [...T, P];

type arr1 = [1, 2];
type arr2 = Push<arr1, 3>; // [1, 2, 3]
type len1 = arr1['length'] // 2
type len2 = arr2['length']; // 3

確實(shí)實(shí)現(xiàn)了 +1操作 ,加法應(yīng)該是可以解決了,+n 就是循環(huán)n次,結(jié)束條件就是結(jié)果為n

所以加法運(yùn)算最后可以轉(zhuǎn)成元祖后計(jì)算長度,類似 JavaScript的Array(n).fill(0),第一步實(shí)現(xiàn) 數(shù)字轉(zhuǎn)array

數(shù)字轉(zhuǎn)array

type ArrOf<T extends number, P extends Array<0> = []> = {
    ['loop']: ArrOf<T, [...P, 0]>;
    ['result']: P;
}[P['length'] extends T ? 'result' : 'loop'];

type arrof1 = ArrOf<5>; // [0, 0, 0, 0, 0]

因?yàn)槲覀冃枰f歸后再跳出條件,最后返回值,所以可以構(gòu)造一個(gè)對象后獲取key,而key就是跳出循環(huán)的關(guān)鍵,跳出循環(huán)的判斷就是 元祖的長度等于輸入的數(shù)

基于以上實(shí)現(xiàn),我們可以得到add的完整實(shí)現(xiàn)了

type ADD<A extends number, B extends number> = [...ArrOf<A>, ...ArrOf<B>]['length'];

type add1 = ADD<3, 4>; // 7

雖然可以推算出結(jié)果,但是給我報(bào)了一個(gè)warning

A rest element type must be an array type.

我覺得可能他推算不出來返回的是array,所以需要我們聲明ArrOf返回的數(shù)都是array,類似 Array.from

type ArrFrom<T> = T extends Array<T> ? T : T;

type ADD<A extends number, B extends number> = [...ArrFrom<ArrOf<A>>, ...ArrFrom<ArrOf<B>>]['length'];

加法和遞歸都被搞定了,接下來看看非負(fù)數(shù)的問題

非負(fù)數(shù)判斷

再重新看看之前的分析,負(fù)數(shù)有什么特殊的地方,負(fù)數(shù)多個(gè)符號顯示,且符號固定是第一位

type str11 = 'abcde';
type str12 = str11[0]; // string

看來并不能通過下標(biāo)來取巧,那我們只能上 infer 了

type getFirst<T extends string> = T extends `${infer P}${string}` ? P : T;

type str11 = 'abcde';
type str12 = getFirst<str11>; // a

所以我們可以把數(shù)字轉(zhuǎn)換字符串后求得符號,然后得出負(fù)數(shù)的判斷

type FirstStr<T extends number> = `${T}` extends `${infer P}${string}` ? P : T;

type isFu<T extends number> = FirstStr<T> extends '-' ? true : false;

type isFu1 = isFu<0>; // false
type isFu2 = isFu<12>; // false
type isFu3 = isFu<-6>; // true
type isFu4 = isFu<-0>; // true

實(shí)現(xiàn)斐波那契

所有的部分都就緒了,實(shí)現(xiàn)一下斐波那契

type ArrOf<T extends number, P extends Array<0> = []> = {
    ['loop']: ArrOf<T, [...P, 0]>;
    ['result']: P;
}[P['length'] extends T ? 'result' : 'loop'];
// 第8行提示結(jié)果可能不是array
type ArrFrom<T> = T extends Array<T> ? T : T;

type ADD<A extends number, B extends number> = [...ArrFrom<ArrOf<A>>, ...ArrFrom<ArrOf<B>>]['length'];
// 第23行提示結(jié)果可能不是number
type NumberFrom<T> = T extends number ? T : T & number;

type ADD2<A extends number, B extends number> = NumberFrom<ADD<A, B>>;

type FirstStr<T extends number> = `${T}` extends `${infer P}${string}` ? P : T;
// 添加負(fù)數(shù)判斷
type isFu<T extends number> = FirstStr<T> extends '-' ? true : false;

type FIB<T extends number, A extends number = 0, B extends number = 1, N extends number = 0> = isFu<T> extends true
    ? never
    : T extends 0 | 1
? T
: {
    ['loop']: FIB<T, B, ADD2<A, B>, ADD2<N, 1>>;
    ['result']: B;
}[T extends ADD2<N, 1> ? 'result' : 'loop'];

type FIFU1 = FIB<-6> // never
type FI0 = FIB<0> // 0
type FI1 = FIB<1>; // 1
type FI2 = FIB<2>; // 1
type FI3 = FIB<3>; // 2
type FI4 = FIB<4>; // 3
type FI5 = FIB<5>; // 5
type FI6 = FIB<6>; // 8
type FI7 = FIB<7>; // 13
type FI8 = FIB<8>; // 21
type FI9 = FIB<9>; // 34

總結(jié)

到此這篇關(guān)于用typescript類型來推算斐波那契的文章就介紹到這了,更多相關(guān)typescript推算斐波那契內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • javascript獲取dom的下一個(gè)節(jié)點(diǎn)方法

    javascript獲取dom的下一個(gè)節(jié)點(diǎn)方法

    這篇文章主要介紹了javascript獲取dom的下一個(gè)節(jié)點(diǎn)方法,實(shí)現(xiàn)在頁面點(diǎn)擊加減按鈕數(shù)字的累加,需要的朋友可以參考下
    2014-09-09
  • JS window.opener返回父頁面的應(yīng)用

    JS window.opener返回父頁面的應(yīng)用

    網(wǎng)上支付開發(fā)分為支付平臺和客戶端兩部分。當(dāng)客戶端進(jìn)入支付平臺時(shí),需要在新窗體打開支付平臺頁面。
    2009-10-10
  • 微信小程序跳轉(zhuǎn)外部鏈接的詳細(xì)實(shí)現(xiàn)方法

    微信小程序跳轉(zhuǎn)外部鏈接的詳細(xì)實(shí)現(xiàn)方法

    寫這個(gè)是因?yàn)樽罱〕绦虻囊粋€(gè)需求需要從小程序跳轉(zhuǎn)到客戶的官網(wǎng),或者其他外部報(bào)名鏈接,下面這篇文章主要給大家介紹了關(guān)于微信小程序跳轉(zhuǎn)外部鏈接的詳細(xì)實(shí)現(xiàn)方法,需要的朋友可以參考下
    2022-10-10
  • 微信小程序中使用wxss加載圖片并實(shí)現(xiàn)動(dòng)畫效果

    微信小程序中使用wxss加載圖片并實(shí)現(xiàn)動(dòng)畫效果

    記錄微信小程序中使用wxss加載圖片并實(shí)現(xiàn)動(dòng)畫的方式,最終實(shí)現(xiàn)loading效果。本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-08-08
  • 百度搜索框智能提示案例jsonp

    百度搜索框智能提示案例jsonp

    這篇文章主要介紹了百度搜索框智能提示案例jsonp的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11
  • JavaScript通過HTML的class來獲取HTML元素的方法總結(jié)

    JavaScript通過HTML的class來獲取HTML元素的方法總結(jié)

    除了getElementsByClassName()函數(shù),我們可以自己動(dòng)手編寫程式來通過class獲取元素,接下來我們整理了一下JavaScript通過HTML的class來獲取HTML元素的方法總結(jié),需要的朋友可以參考下
    2016-05-05
  • 詳解javascript中的Strict模式

    詳解javascript中的Strict模式

    我們都知道javascript是一個(gè)弱類型語言,在ES5之前,javascript的程序編寫具有很強(qiáng)的隨意性,我可以稱之為懶散模式(sloppy mode)。比如可以使用未定義的變量,可以給對象中的任意屬性賦值并不會拋出異常等等。本文將詳細(xì)介紹javascript中的Strict模式。
    2021-06-06
  • JavaScript 獲得選中文本內(nèi)容的方法

    JavaScript 獲得選中文本內(nèi)容的方法

    今天希望實(shí)現(xiàn)一個(gè),直接在網(wǎng)頁上選中文本,點(diǎn)擊收藏夾的鏈接(javascript)即可彈出新窗口(類似“百度搜藏”和“QQ書簽”),新窗口中的文本框即顯示了選中的文本。
    2009-02-02
  • 新增加的內(nèi)容是如何將div的scrollbar自動(dòng)移動(dòng)最下面

    新增加的內(nèi)容是如何將div的scrollbar自動(dòng)移動(dòng)最下面

    在做動(dòng)態(tài)增長的div時(shí),一般都是將內(nèi)容append到div的最下面,但這會帶來一個(gè)比較蛋疼的問題,那就是新增加的內(nèi)容會被遮在最下面,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下
    2014-01-01
  • H5+C3+JS實(shí)現(xiàn)五子棋游戲(AI篇)

    H5+C3+JS實(shí)現(xiàn)五子棋游戲(AI篇)

    這篇文章主要為大家詳細(xì)介紹了H5+C3+JS實(shí)現(xiàn)五子棋游戲AI篇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09

最新評論