ホームページ  >  記事  >  ウェブフロントエンド  >  TypeScript でコードを書くときにやめるべき 10 の悪い習慣

TypeScript でコードを書くときにやめるべき 10 の悪い習慣

青灯夜游
青灯夜游転載
2021-04-28 11:56:042119ブラウズ

TypeScript でコードを書くときにやめるべき 10 の悪い習慣

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 または unknown にのみ適用され、すべての仮想値には適用されません。

#3.

任意のタイプを自由に使用してください

この習慣はどのようなものですか

構造がよくわからない場合は、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

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[]
}
に変更してくださいこれが悪い習慣である理由

any

は、基本的にすべての型チェックを無効にするため、非常に便利です。公式に提供されている型でも

any がよく使用されます。たとえば、TypeScript チームは、上記の例の response.json() の型を Promise 2cfd83bcbfaff9bacc12c0937fd77054 に設定します。 これを実行してはいけない理由

基本的にすべての型チェックを無効にします。 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 コンパイラが自動的に推論できない型が含まれていることがよくあります。この時点で、tsconfig

の設定を変更することなく、

as SomeOtherType を使用して変換を高速化できます。 これを実行してはいけない理由

Type Guard

は、すべてのチェックが明示的であることを保証します。

5.

テストと同様に

この習慣はどのようなものですか

作成は不完全ですテストを書くときのユースケース。
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
}

どのようにすべきか

どの組み合わせが存在し、どの組み合わせが存在しないのかを明確にしてください。
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
}

なぜこれが悪い習慣なのでしょうか?

型を分割する代わりに、プロパティをオプションとしてマークするほうが簡単で、生成されるコードも少なくなります。また、構築される製品についてのより深い理解も必要となり、製品の設計が変更された場合にはコードの使用が制限される可能性があります。

これを行うべきではない理由

型システムの最大の利点は、実行時チェックの代わりにコンパイル時チェックを使用できることです。より明示的な型付けにより、すべての 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 &#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''

为什么不该这样做

与很多编码时的便捷方式一样,使用 !! 实际上是混淆了代码的真实含义。这使得新开发人员很难理解代码,无论是对一般开发人员来说还是对 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

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

以上がTypeScript でコードを書くときにやめるべき 10 の悪い習慣の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。