我 JS 寫的好好的,為什么要用那么復(fù)雜的TS
點擊上方?前端瓶子君,關(guān)注公眾號
回復(fù)算法,加入前端編程面試算法每日一題群
前言
我JS寫的好好的,為啥要用TS寫呢?
本文寫給那些完全沒有用過TS,也沒有使用過結(jié)構(gòu)化語言,對TS有一定的心智負擔(dān)的前端新手同學(xué)。
面對鋪天蓋地的TS怎么好怎么好的文章,項目中還沒真正開始使用到TS的小伙伴,可能只是看了很多的掘金文章,或者看了一遍官方文檔,腦子里基本上都是:嗯,是的,我知道TS好,我知道在變量后面加一個冒號一個類型,就可以限制變量,是不是所有的變量或者函數(shù)都要寫?為什么我寫了返回類型,VSCode還是提示返回值是any類型?泛型好復(fù)雜,什么時候要用泛型?接口類型定義要寫在哪?
來,我們掰開揉碎一點點講。
TS是誰寫給誰看/用的?
先說結(jié)論:TS是定義者給使用者寫的。為了讓使用者更方便(VSCode提示)以及更安全(約束)的使用他提供的方法或者類。
使用TS,是有兩個身份的,定義和使用。
VSCode提示
例如:定義者指定了一個方法:
export?function?foo(name:?string):?number?{
??return?name.length
}
復(fù)制代碼
那么作為使用者, 你會很清晰的通過VSCode的提示了解到該函數(shù)的參數(shù)和返回值信息:

而不需要去看源碼,要知道,一些復(fù)雜的方法,如果沒有良好的注釋,看源碼都不一定能很快的判斷出來參數(shù)和返回值類型。
巧用注釋
為了提供更完美的VSCode提示信息,我們還可以給方法加一個注釋:
/**?foo?function
?*?@description?count?string?size
?*/
export?function?foo(name:?string):?number?{
??return?name.length
}
復(fù)制代碼
這時候使用者看到的是:

所以,當(dāng)你要提供一個方法或者類給別人用的時候,就需要把類型約束好,這樣才能讓使用者更好的使用。這里的提供給別人使用,往大了說就是提供一個第三方類庫或者框架給別人用,如:axios lodash等,往小了說可能就是提取一個公用的方法到你的utils文件夾下。
類型推斷
其實也不是所有的變量或者返回值都需要手動去設(shè)置類型,通過類型推斷[1],可以少些很多代碼。
我們看下面的例子:
export?function?splitString(str:?string)?{
??const?separator?=?','
??return?str.split(separator)
}
復(fù)制代碼
這里的separator就可以不用寫成separator:string,TS會進行類型推斷。
進一步,返回類型我們也可以不用定義,TS會根據(jù)split方法的返回類型來推斷splitString的返回類型。

類型推論只適用于一些簡單的類型,復(fù)雜的情況還是需要手動定義??梢酝ㄟ^VSCode的提示檢測是否正確推斷了類型。
說的極端一點,TS就是為了讓使用者爽,有更好的提示和約束,讓你知道你是否有正確安全的使用提供的方法。而不是為了增加你的工作量和心智負擔(dān)。
VSCode沒有正確提示
如果你為你的項目路徑設(shè)置了別名alias,那么有可能出現(xiàn)引入的方法沒有正確提示的情況。

我們通過別名引入,splitString方法已經(jīng)沒有正確的類型提示了。因為TS不能正確的解析這個目標(biāo)文件@/foo/b,我們可以在tsconfig.json這里的compilerOptions選項添加一個paths配置:
{
????"compilerOptions":?{
????????"paths":?{
??????????"@/*":?["src/*"]
????????}
????}
}
復(fù)制代碼
這樣就可以正確解析別名下文件了。
什么時候用泛型
要知道這個問題之前,你首先要知道什么是泛型,泛型解決了什么問題??梢韵瓤纯?span style="font-weight: bold;color: #ffb11b;padding: 3px;">文檔[2]。
在了解了泛型是讓一個組件支持多種類型之后。如果你還不知道什么時候用泛型,那就是你還不需要用。等你遇到了痛點,你自然就會想到泛型了。
比如你定義了一個方法:
function?foo?(arg:number):number?{
????return?arg
}
復(fù)制代碼
當(dāng)你需要讓這個方法支持string類型的時候,你不使用泛型的話,你可能這么寫:
function?foo(arg:?number?|?string):?number?|?string?{
??return?arg
}
復(fù)制代碼
這里有個問題,會出現(xiàn)傳入number,返回string這樣的情況,不夠嚴謹。
這個時候你就會想到泛型了。
function?foo(arg:?T):?T?{
??return?arg
}
復(fù)制代碼
當(dāng)然,泛型的玩法不都是那么簡單的,想要玩出更高階的泛型寫法,可以多看看第三方庫寫的類型定義文件,看看別人是怎么寫各種泛型的。
類型定義在哪?
這個問題跟上面的問題是一樣的,當(dāng)你不知道這玩意什么時候用,那你應(yīng)該是還用不到這個玩意兒。
簡單的不重用的就直接寫,如上面的示例方法。
需要重用的一般來說就在方法實現(xiàn)的文件夾自定義一個類型,并export出去,方便其他使用者使用。
export?type?fooItem?=?string?|?number?|?null
function?foo(arg:fooItem):void?{
????console.log(arg)
}
復(fù)制代碼
你也可以用一個文件夾,專門放各種公用數(shù)據(jù)類型。比如在定義前后端接口數(shù)據(jù)的時候,就可以這么干:
//?./src/model/user.ts
export?interface?userReq?{
??username:?string
??password:?string
}
export?interface?userRes?{
??nickname:?string
??avatar?:?string
??age:?number
}
復(fù)制代碼
總結(jié)
本文沒有講TS的技巧,沒有講TS的優(yōu)點,就是針對我所看到的新手同學(xué)遇到一些心智方面的問題,基于個人經(jīng)驗進行簡單的解答和講解,講的比較凌亂。
其實TS沒有想象的那么復(fù)雜,TS的初衷是在幫助開發(fā)者,服務(wù)開發(fā)者,要享受TS帶來的便捷和快感。結(jié)尾用一句幾乎每個用過TS的人都會說的話:
用了TS就回不去JS
來源:Kaiser
https://juejin.cn/post/6953500339425247246
