前言
在群里看到一些問題和言論:為什么你們這么喜歡“類型體操”?為什么我根本學不下去 TypeScript?我最討厭那些做類型體操的了;為什么我學了沒過多久馬上又忘了?
有感于這些問題,我想從最簡單的一個角度來切入介紹一下 TypeScript,并向大家介紹并不是只要是個類型運算就是體操。并在文中介紹一種基本思想作為你使用類型系統(tǒng)的基本指引。
引子
我將從一個相對簡單的 API 的設計過程中闡述關于類型的故事。在這里我們可以假設我們現(xiàn)在是一個工具的開發(fā)者,然后我們需要設計一個 API 用于從對象中拿取指定的一些 key 作為一個新的對象返回給外面使用。
垃圾 TypeScript
一個人說:我才不用什么破類型,我寫代碼就是要沒有類型,我就是要隨心所欲的寫。然后寫下了這段代碼。
declarefunctionpick(target:any,...keys:any):any
他的用戶默默的寫下了這段代碼:
pick(undefined,'a',1).b
寫完運行,發(fā)現(xiàn)問題大條了,控制臺一堆報錯,接口數(shù)據(jù)也提交不上去了,怎么辦呢?
剛學 TypeScript
一個人說:稍微檢查一下傳入類型就好了,別讓人給我亂傳參數(shù)就行。
declarefunctionpick(target:Record,...keys:string[]):unknown
很好,上面的問題便不復存在了,API 也是基本可用的了。但是!當對象復雜的時候,以及字段并不是短單詞長度的時候就會發(fā)現(xiàn)了一個沒解決的問題。
pick({abcdefghijkl:'123'},'abcdefghikjl')
從肉眼角度上,我們很難發(fā)現(xiàn)這前后的不一致,所以我們?yōu)槭裁匆屨{用方的用戶自己去 check 自己的字段有沒有寫對呢?
不就 TypeScript
一個人說:這還不簡單,用個泛型加 keyof 不就行了。
declarefunctionpick< ??T?extends?Record>(target:T,...keys:(keyofT)[]):unknown
我們又進一步解決的上面的問題,但是!還是有著相似的問題,雖然我們不用檢查 keys 是不是傳入的是一個正確的值了,但是我們實際上對返回的值也存在一個類似的問題。
pick({abcdefghijkl:'123'},'abcdefghijkl').abcdefghikjl
一點小小的拓展
在這里我們看起來似乎是一個很簡單的功能,但實際上蘊含著一個比較重要的信息。
為什么我們之前的方式都拿不到用戶傳入進來的類型信息呢?是有原因的,當我們設計的 API 的時候,前面的角度是從,如何校驗類型方向進行的思考。
而這里是嘗試去通過約定好的一種規(guī)則,通過 TypeScript 的隱式類型推斷獲得到傳入的類型,再通過約定的規(guī)則轉化出一種新的類型約束來對用戶的輸入進行限制。
算算 TypeScript
一個人說:好辦,算出來一個新的類型就好了。
declarefunctionpick< ??T?extends?Record, KeysextendskeyofT >(target:T,...keys:Keys[]):{ [KinKeys]:T[K] }
到這里已經(jīng)是對類型的作用有了基礎的了解了,能寫出來符合開發(fā)者所能接受的類型相對友好的代碼了。我們可以再來思考一些更特殊的情況:
//輸入了重復的key pick({a:''},'a','a')
完美 TypeScript
到這里,我們便是初步開始了類型“體操”。但是在本篇里,我們不去分析它。
exporttypeL2T=[L]extends[never] ?[] :LextendsinferLItem ?[LItem?,...L2T,LAlias>] :never declarefunctionpick< ??T?extends?Record, KeysextendsL2T >(target:T,...keys:Keys):Pick constx0=pick({a:'1',b:'2'},'a') console.log(x0.a) //@ts-expect-error console.log(x0.b) constx1=pick({a:'1',b:'2'},'a','a') //^^^^^^^^ //TS2345:Argumentoftype'["a","a"]'isnotassignabletoparameteroftype'["a"?,"b"?]|["b"?,"a"?]'. //Type'["a","a"]'isnotassignabletotype'["a"?,"b"?]'. //Typeatposition1insourceisnotcompatiblewithtypeatposition1intarget. //Type'"a"'isnotassignabletotype'"b"'.
一個相對來說比較完美的 pick 函數(shù)便完成了。
總結
我們再來回到我們的標題吧,從我對大多數(shù)人的觀察來說,很多的人開始來使用 TypeScript 有幾種原因:
看到大佬們都在玩,所以自己也想來“玩”,然后為了過類型校驗而去寫
看到一些成熟的項目在使用 TypeScript ,想?yún)⑴c貢獻,參與過程中為了讓類型通過而想辦法去解決類型報錯
公司整體技術棧采用的是 TypeScript ,要用 TypeScript 進行業(yè)務編寫,從而為了過類型檢查和 review 而去解決類型問題
諸如此類的問題還有很多,我將這種都劃分為「為了解決類型檢查的問題」而進行的類型編程,這也是大多數(shù)人為什么非常不適應 TypeScript,甚至不喜歡他的一個原因。這其實對學習 TypeScript 并不是一個很好的思路,在這里我覺得我們需要站在設計者的角度去對類型系統(tǒng)進行思考。我覺得有以下幾個角度:
類型檢查到位
類型提示友好
類型檢查嚴格
擴展性十足
我們如果站在這幾個角度對我們的 API 進行設計,我們可以發(fā)現(xiàn),開發(fā)者能夠很輕松的將他們需要的代碼編寫出來,而盡量不用去翻閱文檔,查找 example。
希望通過我的這篇分享,大家能對 TypeScript 多一些理解,并參與到生態(tài)中來,守護我們的 JavaScript。
鏈接:https://juejin.cn/post/7248599585751515173
審核編輯:劉清
-
JAVA語言
+關注
關注
0文章
138瀏覽量
20090 -
javascript
+關注
關注
0文章
516瀏覽量
53850 -
java接口
+關注
關注
0文章
2瀏覽量
1165
原文標題:為什么你非常不適應 TypeScript
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論