TypeScript代碼10種壞習(xí)慣

      網(wǎng)友投稿 673 2022-05-30

      近幾年 TypeScript 和 JavaScript 一直在穩(wěn)步發(fā)展。我們?cè)谶^(guò)去寫代碼時(shí)養(yǎng)成了一些習(xí)慣,而有些習(xí)慣卻沒(méi)有什么意義。以下是我們都應(yīng)該改正的 10 個(gè)壞習(xí)慣。

      1.不使用?strict?模式

      沒(méi)有用嚴(yán)格模式編寫?tsconfig.json。

      { "compilerOptions": { "target": "ES2015", "module": "commonjs" } }

      只需啟用?strict?模式即可:

      { "compilerOptions": { "target": "ES2015", "module": "commonjs", "strict": true } }

      在現(xiàn)有代碼庫(kù)中引入更嚴(yán)格的規(guī)則需要花費(fèi)時(shí)間。

      為什么不該這樣做

      更嚴(yán)格的規(guī)則使將來(lái)維護(hù)代碼時(shí)更加容易,使你節(jié)省大量的時(shí)間。

      2. 用?||?定義默認(rèn)值

      使用舊的?||?處理后備的默認(rèn)值:

      function createBlogPost (text: string, author: string, date?: Date) { return { text: text, author: author, date: date || new Date() } }

      使用新的????運(yùn)算符,或者在參數(shù)重定義默認(rèn)值。

      function createBlogPost (text: string, author: string, date: Date = new Date()) return { text: text, author: author, date: date } }

      ???運(yùn)算符是去年才引入的,當(dāng)在長(zhǎng)函數(shù)中使用值時(shí),可能很難將其設(shè)置為參數(shù)默認(rèn)值。

      ???與?||?不同,???僅針對(duì)?null?或?undefined,并不適用于所有虛值。

      3. 隨意使用?any?類型

      當(dāng)你不確定結(jié)構(gòu)時(shí),可以用?any?類型。

      async function loadProducts(): Promise { const response = await fetch('https://api.mysite.com/products') const products: any = await response.json() return products }

      把你代碼中任何一個(gè)使用?any?的地方都改為?unknown

      async function loadProducts(): Promise { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() return products as Product[] }

      any?是很方便的,因?yàn)樗旧辖昧怂械念愋蜋z查。通常,甚至在官方提供的類型中都使用了?any。例如,TypeScript 團(tuán)隊(duì)將上面例子中的?response.json()?的類型設(shè)置為?Promise

      它基本上禁用所有類型檢查。任何通過(guò)?any?進(jìn)來(lái)的東西將完全放棄所有類型檢查。這將會(huì)使錯(cuò)誤很難被捕獲到。

      4.?val as SomeType

      強(qiáng)行告訴編譯器無(wú)法推斷的類型。

      async function loadProducts(): Promise { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() return products as Product[] }

      應(yīng)該怎樣

      這正是?Type Guard?的用武之地。

      function isArrayOfProducts (obj: unknown): obj is Product[] { return Array.isArray(obj) && obj.every(isProduct) } function isProduct (obj: unknown): obj is Product { return obj != null && typeof (obj as Product).id === 'string' } async function loadProducts(): Promise { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() if (!isArrayOfProducts(products)) { throw new TypeError('Received malformed products API response') } return products }

      從 JavaScript 轉(zhuǎn)到 TypeScript 時(shí),現(xiàn)有的代碼庫(kù)通常會(huì)對(duì) TypeScript 編譯器無(wú)法自動(dòng)推斷出的類型進(jìn)行假設(shè)。在這時(shí),通過(guò)?as SomeOtherType?可以加快轉(zhuǎn)換速度,而不必修改?tsconfig?中的設(shè)置。

      Type Guard?會(huì)確保所有檢查都是明確的。

      5. 測(cè)試中的?as any

      編寫測(cè)試時(shí)創(chuàng)建不完整的用例。

      interface User { id: string firstName: string lastName: string email: string } test('createEmailText returns text that greats the user by first name', () => { const user: User = { firstName: 'John' } as any expect(createEmailText(user)).toContain(user.firstName) }

      如果你需要模擬測(cè)試數(shù)據(jù),請(qǐng)將模擬邏輯移到要模擬的對(duì)象旁邊,并使其可重用。

      interface User { id: string firstName: string lastName: string email: string } class MockUser implements User { id = 'id' firstName = 'John' lastName = 'Doe' email = 'john@doe.com' } test('createEmailText returns text that greats the user by first name', () => { const user = new MockUser() expect(createEmailText(user)).toContain(user.firstName) }

      在給尚不具備廣泛測(cè)試覆蓋條件的代碼編寫測(cè)試時(shí),通常會(huì)存在復(fù)雜的大數(shù)據(jù)結(jié)構(gòu),但要測(cè)試的特定功能僅需要其中的一部分。短期內(nèi)不必關(guān)心其他屬性。

      在某些情況下,被測(cè)代碼依賴于我們之前認(rèn)為不重要的屬性,然后需要更新針對(duì)該功能的所有測(cè)試。

      6. 可選屬性

      將屬性標(biāo)記為可選屬性,即便這些屬性有時(shí)不存在。

      interface Product { id: string type: 'digital' | 'physical' weightInKg?: number sizeInMb?: number }

      明確哪些組合存在,哪些不存在。

      interface Product { id: string type: 'digital' | 'physical' } interface DigitalProduct extends Product { type: 'digital' sizeInMb: number } interface PhysicalProduct extends Product { type: 'physical' weightInKg: number }

      將屬性標(biāo)記為可選而不是拆分類型更容易,并且產(chǎn)生的代碼更少。它還需要對(duì)正在構(gòu)建的產(chǎn)品有更深入的了解,并且如果對(duì)產(chǎn)品的設(shè)計(jì)有所修改,可能會(huì)限制代碼的使用。

      類型系統(tǒng)的最大好處是可以用編譯時(shí)檢查代替運(yùn)行時(shí)檢查。通過(guò)更顯式的類型,能夠?qū)赡懿槐蛔⒁獾腻e(cuò)誤進(jìn)行編譯時(shí)檢查,例如確保每個(gè)?DigitalProduct?都有一個(gè)?sizeInMb。

      7. 用一個(gè)字母通行天下

      用一個(gè)字母命名泛型

      function head (arr: T[]): T | undefined { return arr[0] }

      提供完整的描述性類型名稱。

      function head (arr: Element[]): Element | undefined { return arr[0] }

      這種寫法最早來(lái)源于C++的范型庫(kù),即使是 TS 的官方文檔也在用一個(gè)字母的名稱。它也可以更快地輸入,只需要簡(jiǎn)單的敲下一個(gè)字母?T?就可以代替寫全名。

      通用類型變量也是變量,就像其他變量一樣。當(dāng) IDE 開(kāi)始向我們展示變量的類型細(xì)節(jié)時(shí),我們已經(jīng)慢慢放棄了用它們的名稱描述來(lái)變量類型的想法。例如我們現(xiàn)在寫代碼用?const name ='Daniel',而不是?const strName ='Daniel'。同樣,一個(gè)字母的變量名通常會(huì)令人費(fèi)解,因?yàn)椴豢绰暶骶秃茈y理解它們的含義。

      8. 對(duì)非布爾類型的值進(jìn)行布爾檢查

      通過(guò)直接將值傳給?if?語(yǔ)句來(lái)檢查是否定義了值。

      function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }

      明確檢查我們所關(guān)心的狀況。

      function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }

      編寫簡(jiǎn)短的檢測(cè)代碼看起來(lái)更加簡(jiǎn)潔,使我們能夠避免思考實(shí)際想要檢測(cè)的內(nèi)容。

      也許我們應(yīng)該考慮一下實(shí)際要檢查的內(nèi)容。例如上面的例子以不同的方式處理?countOfNewMessages?為?0?的情況。

      9. ”棒棒“運(yùn)算符

      寫TypeScript代碼的10種壞習(xí)慣

      將非布爾值轉(zhuǎn)換為布爾值。

      function createNewMessagesResponse (countOfNewMessages?: number) { if (!!countOfNewMessages) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }

      明確檢查我們所關(guān)心的狀況。

      function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }

      對(duì)某些人而言,理解?!!?就像是進(jìn)入 JavaScript 世界的入門儀式。它看起來(lái)簡(jiǎn)短而簡(jiǎn)潔,如果你對(duì)它已經(jīng)非常習(xí)慣了,就會(huì)知道它的含義。這是將任意值轉(zhuǎn)換為布爾值的便捷方式。尤其是在如果虛值之間沒(méi)有明確的語(yǔ)義界限時(shí),例如?null、undefined?和?''。

      與很多編碼時(shí)的便捷方式一樣,使用?!!?實(shí)際上是混淆了代碼的真實(shí)含義。這使得新開(kāi)發(fā)人員很難理解代碼,無(wú)論是對(duì)一般開(kāi)發(fā)人員來(lái)說(shuō)還是對(duì) JavaScript 來(lái)說(shuō)都是新手。也很容易引入細(xì)微的錯(cuò)誤。在對(duì)“非布爾類型的值”進(jìn)行布爾檢查時(shí)?countOfNewMessages?為?0?的問(wèn)題在使用?!!?時(shí)仍然會(huì)存在。

      10.?!= null

      棒棒運(yùn)算符的小弟?! = null使我們能同時(shí)檢查?null?和?undefined。

      function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages != null) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }

      明確檢查我們所關(guān)心的狀況。

      function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }

      如果你的代碼在?null?和?undefined?之間沒(méi)有明顯的區(qū)別,那么?!= null?有助于簡(jiǎn)化對(duì)這兩種可能性的檢查。

      盡管?null?在 JavaScript早期很麻煩,但 TypeScript 處于?strict?模式時(shí),它卻可以成為這種語(yǔ)言中寶貴的工具。一種常見(jiàn)模式是將?null?值定義為不存在的事物,將?undefined?定義為未知的事物,例如?user.firstName === null?可能意味著用戶實(shí)際上沒(méi)有名字,而?user.firstName === undefined?只是意味著我們尚未詢問(wèn)該用戶(而?user.firstName ===?的意思是字面意思是?''?。

      翻譯:瘋狂的技術(shù)宅

      原文:https://startup-cto.net/10-bad-typescript-habits-to-break-this-year/

      JavaScript TypeScript

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:深度實(shí)踐OpenStack:基于Python的OpenStack組件開(kāi)發(fā)—3.3.3 字符串和列表
      下一篇:技術(shù)干貨| MindSpore新一代自主研發(fā)分子模擬庫(kù):Mind-Sponge
      相關(guān)文章
      亚洲一区二区三区精品视频 | 国产国拍亚洲精品福利| 亚洲精品视频在线观看免费| 亚洲AV日韩精品久久久久| 亚洲午夜福利717| 国产亚洲美日韩AV中文字幕无码成人| 国产亚洲精品美女久久久久久下载| 久久亚洲精品国产亚洲老地址| 亚洲精品熟女国产| 亚洲欧洲精品视频在线观看| 亚洲美女激情视频| 亚洲视频欧洲视频| 亚洲国产综合精品| 亚洲一区二区影视| 亚洲伊人久久大香线蕉AV| 亚洲日韩亚洲另类激情文学| 亚洲欧美成aⅴ人在线观看| 亚洲乱码日产精品一二三| 亚洲精品无码mⅴ在线观看| 亚洲av无码av在线播放| 日本中文一区二区三区亚洲| 亚洲国产精品成人久久蜜臀| 亚洲AV无码乱码在线观看性色扶 | 亚洲va无码手机在线电影| 亚洲成a人片在线观看日本| 亚洲AV无码成人网站久久精品大 | 亚洲一卡2卡4卡5卡6卡残暴在线| 亚洲高清在线mv| 亚洲精品在线观看视频| 亚洲欧洲日韩不卡| 亚洲国产视频一区| 国产午夜亚洲精品| 亚洲三级在线免费观看| 亚洲熟妇丰满xxxxx| 久久丫精品国产亚洲av不卡| 亚洲国产精品久久丫| 亚洲中文字幕无码中文字| 国产AV无码专区亚洲AV琪琪| 精品亚洲456在线播放| 亚洲成?v人片天堂网无码| 中文字幕亚洲一区二区三区|