近年來 TypeScript 和 JavaScript 一直在穩步發展。我們在過去寫程式碼時養成了一些習慣,而有些習慣卻沒有什麼意義。以下是我們都應該改正的 10 個壞習慣。
strict
模式沒有用嚴格模式寫tsconfig.json
。
{ "compilerOptions": { "target": "ES2015", "module": "commonjs" } }
只需啟用strict
模式:
{ "compilerOptions": { "target": "ES2015", "module": "commonjs", "strict": true } }
在現有程式碼庫中引入更嚴格的規則需要花費時間。
更嚴格的規則使將來維護程式碼時更加容易,使你節省大量的時間。
||
定義預設值#使用舊的 ||
處理後備的預設值:
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 } }
?? 運算子是去年才引入的,當在長函數中使用值時,可能很難將其設定為參數預設值。
?? 與
|| 不同,
??
,並不適用於所有虛值。
#這個習慣看起來是什麼樣的
#當你不確定結構時,可以用
async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') 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<Product[]> {
const response = await fetch(&#39;https://api.mysite.com/products&#39;)
const products: unknown = await response.json()
return products as Product[]
}</pre><div class="contentsignin">登入後複製</div></div><div class="contentsignin">登入後複製</div></div>
是很方便的,因為它基本上禁用了所有的類型檢查。通常,甚至在官方提供的類型中都使用了 any
。例如,TypeScript 團隊將上面範例中的
。
進來的東西將完全放棄所有類型檢查。這將會使錯誤很難被捕獲。
async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() return products as Product[] }
應該怎樣
這正是
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<Product[]> { 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 轉到TypeScript 時,現有的程式碼庫通常會對TypeScript 編譯器無法自動推斷出的類型進行假設。在這時,透過
中的設定。
會確保所有檢查都是明確的。
#在撰寫測試時會建立不完整的用例。
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) }
如果你需要模擬測試數據,請將模擬邏輯移到要模擬的物件旁邊,並使其可重複使用。
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) }
#將屬性標記為可選屬性,即便這些屬性有時不存在。
interface Product { id: string type: 'digital' | 'physical' 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: &#39;digital&#39; | &#39;physical&#39;
}
interface DigitalProduct extends Product {
type: &#39;digital&#39;
sizeInMb: number
}
interface PhysicalProduct extends Product {
type: &#39;physical&#39;
weightInKg: number
}</pre><div class="contentsignin">登入後複製</div></div>
為什麼會有這種壞習慣
用一个字母命名泛型
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 ='Daniel'
,而不是 const strName ='Daniel'
。同样,一个字母的变量名通常会令人费解,因为不看声明就很难理解它们的含义。
通过直接将值传给 if
语句来检查是否定义了值。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
明确检查我们所关心的状况。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
编写简短的检测代码看起来更加简洁,使我们能够避免思考实际想要检测的内容。
也许我们应该考虑一下实际要检查的内容。例如上面的例子以不同的方式处理 countOfNewMessages
为 0
的情况。
将非布尔值转换为布尔值。
function createNewMessagesResponse (countOfNewMessages?: number) { if (!!countOfNewMessages) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
明确检查我们所关心的状况。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
对某些人而言,理解 !!
就像是进入 JavaScript 世界的入门仪式。它看起来简短而简洁,如果你对它已经非常习惯了,就会知道它的含义。这是将任意值转换为布尔值的便捷方式。尤其是在如果虚值之间没有明确的语义界限时,例如 null
、undefined
和 ''
。
与很多编码时的便捷方式一样,使用 !!
实际上是混淆了代码的真实含义。这使得新开发人员很难理解代码,无论是对一般开发人员来说还是对 JavaScript 来说都是新手。也很容易引入细微的错误。在对“非布尔类型的值”进行布尔检查时 countOfNewMessages
为 0
的问题在使用 !!
时仍然会存在。
!= null
棒棒运算符的小弟 ! = null
使我们能同时检查 null
和 undefined
。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages != null) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
明确检查我们所关心的状况。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
如果你的代码在 null
和 undefined
之间没有明显的区别,那么 != 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中文網其他相關文章!