首頁 > web前端 > js教程 > 主體

10種TypeScript編寫程式碼時應改正的壞習慣

青灯夜游
發布: 2021-04-28 11:56:04
轉載
2118 人瀏覽過

10種TypeScript編寫程式碼時應改正的壞習慣

近年來 TypeScript 和 JavaScript 一直在穩步發展。我們在過去寫程式碼時養成了一些習慣,而有些習慣卻沒有什麼意義。以下是我們都應該改正的 10 個壞習慣。

1.不使用strict 模式

#這個習慣看起來是什麼樣的

沒有用嚴格模式寫tsconfig.json

{
  "compilerOptions": {
    "target": "ES2015",
    "module": "commonjs"
  }
}
登入後複製

應該怎樣

只需啟用strict 模式:

{
  "compilerOptions": {
    "target": "ES2015",
    "module": "commonjs",
    "strict": true
  }
}
登入後複製

為什麼會有這種壞習慣

在現有程式碼庫中引入更嚴格的規則需要花費時間。

為什麼不該這樣做

更嚴格的規則使將來維護程式碼時更加容易,使你節省大量的時間。

2. 用|| 定義預設值

#這個習慣看起來是什麼樣的

#使用舊的 ||  處理後備的預設值:

function createBlogPost (text: string, author: string, date?: Date) {
  return {
    text: text,
    author: author,
    date: date || new Date()
  }
}
登入後複製

應該怎樣

##使用新的

?? 運算符,或在參數重定義預設值。

function createBlogPost (text: string, author: string, date: Date = new Date())
  return {
    text: text,
    author: author,
    date: date
  }
}
登入後複製

為什麼會有這種壞習慣

?? 運算子是去年才引入的,當在長函數中使用值時,可能很難將其設定為參數預設值。

為什麼不該這樣做

??|| 不同,??

#僅針對null

undefined

,並不適用於所有虛值。

3. 隨意使用

any 類型

#這個習慣看起來是什麼樣的 #當你不確定結構時,可以用

any

類型。
async function loadProducts(): Promise<Product[]> {
  const response = await fetch(&#39;https://api.mysite.com/products&#39;)
  const products: any = await response.json()
  return products
}
登入後複製

應該怎樣

把你程式碼中任何一個使用any 的地方都改為unknown <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">async function loadProducts(): Promise&lt;Product[]&gt; { const response = await fetch(&amp;#39;https://api.mysite.com/products&amp;#39;) const products: unknown = await response.json() return products as Product[] }</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>

為什麼會有這種壞習慣

any

是很方便的,因為它基本上禁用了所有的類型檢查。通常,甚至在官方提供的類型中都使用了 any。例如,TypeScript 團隊將上面範例中的

response.json()

的類型設為 Promise

為什麼不該這樣做

它基本上會停用所有類型檢查。任何透過

any

進來的東西將完全放棄所有類型檢查。這將會使錯誤很難被捕獲。

4. val as SomeType

#這個習慣看起來是什麼樣的

強行告訴編譯器無法推斷的型別。

async function loadProducts(): Promise<Product[]> {
  const response = await fetch(&#39;https://api.mysite.com/products&#39;)
  const products: unknown = await response.json()
  return products as Product[]
}
登入後複製
登入後複製

應該怎樣這正是

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 === &#39;string&#39;
}

async function loadProducts(): Promise<Product[]> {
  const response = await fetch(&#39;https://api.mysite.com/products&#39;)
  const products: unknown = await response.json()
  if (!isArrayOfProducts(products)) {
    throw new TypeError(&#39;Received malformed products API response&#39;)
  }
  return products
}
登入後複製

為什麼會有這種壞習慣

從JavaScript 轉到TypeScript 時,現有的程式碼庫通常會對TypeScript 編譯器無法自動推斷出的類型進行假設。在這時,透過

as SomeOtherType

可以加快轉換速度,而不必修改 tsconfig 中的設定。

為什麼不該這樣做

Type Guard

會確保所有檢查都是明確的。

5. 測驗中的as any

#這個習慣看起來是什麼樣的

#在撰寫測試時會建立不完整的用例。

interface User {
  id: string
  firstName: string
  lastName: string
  email: string
}

test(&#39;createEmailText returns text that greats the user by first name&#39;, () => {
  const user: User = {
    firstName: &#39;John&#39;
  } as any
  
  expect(createEmailText(user)).toContain(user.firstName)
}
登入後複製

應該怎樣

如果你需要模擬測試數據,請將模擬邏輯移到要模擬的物件旁邊,並使其可重複使用。

interface User {
  id: string
  firstName: string
  lastName: string
  email: string
}

class MockUser implements User {
  id = &#39;id&#39;
  firstName = &#39;John&#39;
  lastName = &#39;Doe&#39;
  email = &#39;john@doe.com&#39;
}

test(&#39;createEmailText returns text that greats the user by first name&#39;, () => {
  const user = new MockUser()

  expect(createEmailText(user)).toContain(user.firstName)
}
登入後複製

為什麼會有這種壞習慣

在給尚不具備廣泛測試覆蓋條件的程式碼編寫測試時,通常會存在複雜的大數據結構,但要測試的特定功能只需要其中的一部分。短期內不必關心其他屬性。

為什麼不該這樣做

在某些情況下,被測試程式碼依賴我們之前認為不重要的屬性,然後需要更新針對該功能的所有測試。

6. 可選屬性

這個習慣看起來是什麼樣的

#將屬性標記為可選屬性,即便這些屬性有時不存在。

interface Product {
  id: string
  type: &#39;digital&#39; | &#39;physical&#39;
  weightInKg?: number
  sizeInMb?: number
}
登入後複製

應該怎樣

#明確哪些組合存在,哪些不存在。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">interface Product { id: string type: &amp;#39;digital&amp;#39; | &amp;#39;physical&amp;#39; } interface DigitalProduct extends Product { type: &amp;#39;digital&amp;#39; sizeInMb: number } interface PhysicalProduct extends Product { type: &amp;#39;physical&amp;#39; weightInKg: number }</pre><div class="contentsignin">登入後複製</div></div>為什麼會有這種壞習慣

###將屬性標記為可選而不是分割類型更容易,並且產生的程式碼更少。它還需要對正在建置的產品有更深入的了解,並且如果對產品的設計有所修改,可能會限製程式碼的使用。 #########為什麼不該這樣做#########類型系統的最大好處是可以用編譯時檢查代替執行時間檢查。透過更明確的類型,能夠對可能不被注意的錯誤進行編譯時檢查,例如確保每個 ###DigitalProduct### 都有一個 ###sizeInMb###。 ###

7. 用一个字母通行天下

这种习惯看起来是什么样的

用一个字母命名泛型

function head<T> (arr: T[]): T | undefined {
  return arr[0]
}
登入後複製

应该怎样

提供完整的描述性类型名称。

function head<Element> (arr: Element[]): Element | undefined {
  return arr[0]
}
登入後複製

为什么会有这种坏习惯

这种写法最早来源于C++的范型库,即使是 TS 的官方文档也在用一个字母的名称。它也可以更快地输入,只需要简单的敲下一个字母 T 就可以代替写全名。

为什么不该这样做

通用类型变量也是变量,就像其他变量一样。当 IDE 开始向我们展示变量的类型细节时,我们已经慢慢放弃了用它们的名称描述来变量类型的想法。例如我们现在写代码用 const name =&#39;Daniel&#39;,而不是 const strName =&#39;Daniel&#39;。同样,一个字母的变量名通常会令人费解,因为不看声明就很难理解它们的含义。

8. 对非布尔类型的值进行布尔检查

这种习惯看起来是什么样的

通过直接将值传给 if 语句来检查是否定义了值。

function createNewMessagesResponse (countOfNewMessages?: number) {
  if (countOfNewMessages) {
    return `You have ${countOfNewMessages} new messages`
  }
  return &#39;Error: Could not retrieve number of new messages&#39;
}
登入後複製

应该怎样

明确检查我们所关心的状况。

function createNewMessagesResponse (countOfNewMessages?: number) {
  if (countOfNewMessages !== undefined) {
    return `You have ${countOfNewMessages} new messages`
  }
  return &#39;Error: Could not retrieve number of new messages&#39;
}
登入後複製
登入後複製
登入後複製

为什么会有这种坏习惯

编写简短的检测代码看起来更加简洁,使我们能够避免思考实际想要检测的内容。

为什么不该这样做

也许我们应该考虑一下实际要检查的内容。例如上面的例子以不同的方式处理 countOfNewMessages0 的情况。

9. ”棒棒“运算符

这种习惯看起来是什么样的

将非布尔值转换为布尔值。

function createNewMessagesResponse (countOfNewMessages?: number) {
  if (!!countOfNewMessages) {
    return `You have ${countOfNewMessages} new messages`
  }
  return &#39;Error: Could not retrieve number of new messages&#39;
}
登入後複製

应该怎样

明确检查我们所关心的状况。

function createNewMessagesResponse (countOfNewMessages?: number) {
  if (countOfNewMessages !== undefined) {
    return `You have ${countOfNewMessages} new messages`
  }
  return &#39;Error: Could not retrieve number of new messages&#39;
}
登入後複製
登入後複製
登入後複製

为什么会有这种坏习惯

对某些人而言,理解 !! 就像是进入 JavaScript 世界的入门仪式。它看起来简短而简洁,如果你对它已经非常习惯了,就会知道它的含义。这是将任意值转换为布尔值的便捷方式。尤其是在如果虚值之间没有明确的语义界限时,例如 nullundefined&#39;&#39;

为什么不该这样做

与很多编码时的便捷方式一样,使用 !! 实际上是混淆了代码的真实含义。这使得新开发人员很难理解代码,无论是对一般开发人员来说还是对 JavaScript 来说都是新手。也很容易引入细微的错误。在对“非布尔类型的值”进行布尔检查时 countOfNewMessages0 的问题在使用 !! 时仍然会存在。

10. != null

这种习惯看起来是什么样的

棒棒运算符的小弟 ! = null使我们能同时检查 nullundefined

function createNewMessagesResponse (countOfNewMessages?: number) {
  if (countOfNewMessages != null) {
    return `You have ${countOfNewMessages} new messages`
  }
  return &#39;Error: Could not retrieve number of new messages&#39;
}
登入後複製

应该怎样

明确检查我们所关心的状况。

function createNewMessagesResponse (countOfNewMessages?: number) {
  if (countOfNewMessages !== undefined) {
    return `You have ${countOfNewMessages} new messages`
  }
  return &#39;Error: Could not retrieve number of new messages&#39;
}
登入後複製
登入後複製
登入後複製

为什么会有这种坏习惯

如果你的代码在 nullundefined 之间没有明显的区别,那么 != null 有助于简化对这两种可能性的检查。

为什么不该这样做

尽管 null 在 JavaScript早期很麻烦,但 TypeScript 处于 strict 模式时,它却可以成为这种语言中宝贵的工具。一种常见模式是将 null 值定义为不存在的事物,将 undefined 定义为未知的事物,例如 user.firstName === null 可能意味着用户实际上没有名字,而 user.firstName === undefined 只是意味着我们尚未询问该用户(而 user.firstName === 的意思是字面意思是 ''

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

作者:Daniel Bartholomae

译文地址:https://segmentfault.com/a/1190000039368534

更多编程相关知识,请访问:编程入门!!

以上是10種TypeScript編寫程式碼時應改正的壞習慣的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板