TypeScript와 JavaScript는 최근 몇 년간 꾸준히 발전해 왔습니다. 우리는 과거에 코드를 작성할 때 몇 가지 습관을 길러왔는데, 그 중 일부는 별로 의미가 없습니다. 우리 모두가 버려야 할 나쁜 습관 10가지를 소개합니다.
strict
모드를 사용하지 않음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 } }
??
运算符是去年才引入的,当在长函数中使用值时,可能很难将其设置为参数默认值。
??
与 ||
不同,??
仅针对 null
或 undefined
,并不适用于所有虚值。
any
类型当你不确定结构时,可以用 any
类型。
async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') const products: any = await response.json() return products }
把你代码中任何一个使用 any
的地方都改为 unknown
async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() return products as Product[] }
any
是很方便的,因为它基本上禁用了所有的类型检查。通常,甚至在官方提供的类型中都使用了 any
。例如,TypeScript 团队将上面例子中的 response.json()
的类型设置为 Promise <any>
。
它基本上禁用所有类型检查。任何通过 any
进来的东西将完全放弃所有类型检查。这将会使错误很难被捕获到。
val as SomeType
强行告诉编译器无法推断的类型。
async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') 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 === '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 编译器无法自动推断出的类型进行假设。在这时,通过 as SomeOtherType
可以加快转换速度,而不必修改 tsconfig
中的设置。
Type Guard
会确保所有检查都是明确的。
as any
编写测试时创建不完整的用例。
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 }
明确哪些组合存在,哪些不存在。
interface Product { id: string type: 'digital' | 'physical' } interface DigitalProduct extends Product { type: 'digital' sizeInMb: number } interface PhysicalProduct extends Product { type: 'physical' weightInKg: number }
将属性标记为可选而不是拆分类型更容易,并且产生的代码更少。它还需要对正在构建的产品有更深入的了解,并且如果对产品的设计有所修改,可能会限制代码的使用。
类型系统的最大好处是可以用编译时检查代替运行时检查。通过更显式的类型,能够对可能不被注意的错误进行编译时检查,例如确保每个 DigitalProduct
都有一个 sizeInMb
이 습관은 어떻게 생겼나요
tsconfig.json
. 🎜function head<T> (arr: T[]): T | undefined { return arr[0] }
엄격
모드를 활성화하세요: 🎜function head<Element> (arr: Element[]): Element | undefined { return arr[0] }
||
를 사용하여 기본값을 정의하세요||
는 fallback의 기본값을 처리합니다: 🎜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' }
??
연산자는 작년에야 소개되었는데 긴 함수에서 값을 사용할 때 매개변수 기본값으로 설정하기는 매우 어렵습니다. 🎜??
||
와 달리 ??
null
또는 undefine
의 경우에만 모든 가상 값에 적용되지 않습니다. 🎜🎜🎜3. 어떤
유형이든 자유롭게 사용해 보세요any
유형을 사용할 수 있습니다. 🎜function createNewMessagesResponse (countOfNewMessages?: number) { if (!!countOfNewMessages) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
any
를 사용하는 모든 위치를 unknown
🎜function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
any
는 기본적으로 모든 유형 검사를 비활성화하므로 매우 편리합니다. 공식적으로 제공되는 유형에서도 any
가 사용되는 경우가 많습니다. 예를 들어 TypeScript 팀은 위 예에서 response.json()
유형을 Promise <any>
로 설정했습니다. 🎜any
를 통해 들어오는 모든 항목은 모든 유형 검사를 완전히 포기합니다. 이렇게 하면 오류를 잡기가 어려워집니다. 🎜🎜🎜4. val as SomeType
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages != null) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
Type Guard
가 필요합니다. 🎜function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
as SomeOtherType
은 tsconfig
의 설정을 수정하지 않고도 변환 속도를 높일 수 있습니다. 🎜Type Guard
는 모든 검사가 명시적으로 이루어지도록 보장합니다. 🎜🎜🎜5. 테스트에서 무엇이든
DigitalProduct
에 sizeInMb
가 있는지 확인하는 등 눈에 띄지 않을 수 있는 오류에 대한 컴파일 타임 검사가 가능해집니다. 🎜用一个字母命名泛型
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
更多编程相关知识,请访问:编程入门!!
위 내용은 TypeScript로 코드를 작성할 때 버려야 할 10가지 나쁜 습관의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!