文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

TypeScript编写代码时应改正的坏习惯有哪些

2023-06-14 21:42

关注

这篇文章主要介绍了TypeScript编写代码时应改正的坏习惯有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

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  }}
为什么会有这种坏习惯

?? 运算符是去年才引入的,当在长函数中使用值时,可能很难将其设置为参数默认值。

为什么不该这样做

??|| 不同,?? 仅针对 nullundefined,并不适用于所有虚值。

3. 随意使用 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 进来的东西将完全放弃所有类型检查。这将会使错误很难被捕获到。

4. 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 会确保所有检查都是明确的。

5. 测试中的 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)}
为什么会有这种坏习惯

在给尚不具备广泛测试覆盖条件的代码编写测试时,通常会存在复杂的大数据结构,但要测试的特定功能仅需要其中的一部分。短期内不必关心其他属性。

为什么不该这样做

在某些情况下,被测代码依赖于我们之前认为不重要的属性,然后需要更新针对该功能的所有测试。

6. 可选属性

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

将属性标记为可选属性,即便这些属性有时不存在。

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

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 ='Daniel',而不是 const strName ='Daniel'。同样,一个字母的变量名通常会令人费解,因为不看声明就很难理解它们的含义。

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

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

通过直接将值传给 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'}
为什么会有这种坏习惯

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

为什么不该这样做

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

9. ”棒棒“运算符

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

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

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 世界的入门仪式。它看起来简短而简洁,如果你对它已经非常习惯了,就会知道它的含义。这是将任意值转换为布尔值的便捷方式。尤其是在如果虚值之间没有明确的语义界限时,例如 nullundefined''

为什么不该这样做

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

10. != null

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

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

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'}
为什么会有这种坏习惯

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

为什么不该这样做

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

感谢你能够认真阅读完这篇文章,希望小编分享的“TypeScript编写代码时应改正的坏习惯有哪些”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯