paint-brush
構造化とインライン型を使用すると、TypeScript コードベースが損なわれる可能性があります@baransu
1,271 測定値
1,271 測定値

構造化とインライン型を使用すると、TypeScript コードベースが損なわれる可能性があります

Tomasz Cichociński4m2022/10/10
Read on Terminal Reader
Read this story w/o Javascript

長すぎる; 読むには

構造化とインライン型を使用すると、TypeScript が読みにくくなります。構造化を使用すると、TypeScript で読みにくくなる方法を示したいと思います。より小さなヘルパー関数を作成したり、コンポジションに依存してメイン関数のロジックを構築したりすることを思いとどまらせます。関数定義ですべての型が構造化されて窮屈になっている場合、ドキュメンテーション コメントを書く自然な場所はありません。それはコードのスペースが大きいだけで、多くのスペースのコード行を必要とします。さらに、実装の詳細に加えて、実装の詳細にも焦点を当てています。

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - 構造化とインライン型を使用すると、TypeScript コードベースが損なわれる可能性があります
Tomasz Cichociński HackerNoon profile picture
0-item


最近、Jamie Kyle による、破壊、デフォルト パラメータ、およびインライン型の使用に関するツイートを見ました。


そのつぶやきと、最近仕事で目にしたいくつかの React コンポーネントが、このブログ投稿を書くきっかけになりました。構造化とインライン型を使用すると、TypeScript が読みにくくなる可能性があることをお見せしたいと思います!


TypeScript 関数定義はどのように見えますか?

JavaScript と TypeScript では、 functionキーワードまたはラムダ/矢印関数を使用して関数を定義できます。どちらの方法も有効ですが、違いがあります。簡単なsendMessage関数を見てみましょう。実装ロジックは関係ありません。


 // sendMessage function written using `function` keyword function sendMessage(message: string) { // function logic } // same sendMessage written as arrow function const sendMessage = (message: string) => { // function logic };


関数定義が非常に単純な場合、関数は異なる型のいくつかのパラメーターを受け入れます。それらが文字列や数値のようなプリミティブである場合、すべてが読み取り可能です。


メッセージの内容と一緒にいくつかの追加情報をsendMessage関数に渡したいとしましょう。


 function sendMessage(message: { content: string; senderId: string; replyTo?: string; }) { // you can assess content using `message.content` here }


ご覧のとおり、TypeScript では、 typeまたはinterfaceキーワードを使用して型を指定せずに、渡したいmessageオブジェクトのインライン型定義を記述できます。


Destructuring を追加しましょう。関数に大きなmessageオブジェクトを渡す場合、TypeScript を使用すると、渡された引数を分割して、 message変数を何度も繰り返すコード ボイラープレートを減らすことができます。


 function sendMessage({ content, senderId, replyTo, }: { content: string; senderId: string; replyTo?: string; }) { // you have access to `content` directly }


なぜそれが悪い考えだと思うのか、どうすれば改善できるのか?

いいアイデアに見えるかもしれませんが、何回もmessageを書く必要はありませんよね?それほど素晴らしいものではないことがわかりました。私がアンチパターンだと思う5つの理由について話しましょう。


1. データがどこから来ているのかわからない

関数本体を読んでいると、 senderIdが表示され、その関数がどこから来たのかを再確認する必要があります。引数として渡されるか、関数のどこかで計算されますか?


2. ドキュメントを書くのが難しい

関数定義ですべての型が構造化されて窮屈になっている場合、ドキュメンテーション コメントを書く自然な場所はありません。各型フィールド間にコメントを書くこともできますが、それによって関数定義全体がさらに長くなります。渡すデータの簡単な要約を書くことを積極的に思いとどまらせています。


3. そのデータを転送するのは難しい

データが構造化されていない場合、データを転送したい場合は、構造化して新しいオブジェクトにする必要があります。これにより、小さなヘルパー関数を作成したり、コンポジションに依存してメイン関数のロジックを構築したりすることを思いとどまらせます。


4. この関数の外で引数の型を再利用することはできません

メイン関数のロジックを作成するときにヘルパー関数で関数の引数を再利用する必要がある場合は、同じ型のセットを繰り返し入力する必要があります。これにより、タイプをまったく記述しないことが容易になります。


5. かなりのスペースが必要

それに直面しよう。多くの画面スペースを占有するのは、多くのコード行です。さらに、実装の詳細 (関数に渡す引数の内部型) に焦点を当てていますが、これはほとんどの場合、その関数を見ているときには関係ありません。


そのためのタイプを作成するだけです

型を抽出して関数のすぐ上に配置すると、読みやすくなります。ドキュメント コメント用の場所があります。必要に応じて、その型を他のヘルパー関数で再利用し、型定義を 1 か所で変更できます。


 /** * Message to send using XYZ API */ export type MessageToSend = { /** * Markdown string of the user's message */ content: string; /** * Id of the sender user */ senderId: string; /** * Other message ID if this is a reply */ replyTo?: string; }; function sendMessage(message: MessageToSend) { // function logic } function getUserIdsToNotify(message: MessaageToSend) { // function logic }


資力

このブログ投稿を調査する際に使用したリソースのリストを見つけてください。