paint-brush
React プロジェクトを JavaScript から TypeScript に移行する方法@leandronnz
14,519 測定値
14,519 測定値

React プロジェクトを JavaScript から TypeScript に移行する方法

Leandro Nuñez24m2023/10/19
Read on Terminal Reader

長すぎる; 読むには

React プロジェクトを Javascript から TypeScript に移行することは、.js ファイルを .tsx に単に「検索して置換」するだけではありません。これは、新しい規約を学び、型を深く理解し、そして最も重要なことに、コードの信頼性と一貫性についての考え方を変えることを伴う戦略的な動きです。 以下にいくつかの注意事項を示します。 セーフティ ネット: TypeScript はプロジェクトにセーフティ レイヤを導入し、実行時に大混乱を引き起こす前にエラーを検出します。このセーフティ ネットは、一度慣れてしまえば、コードに対する信頼性と全体的な開発速度の面で大きな変化をもたらします。 より明確な通信: 型を使用すると、コードはより明示的に通信できるようになりました。コードを再検討する場合でも、新しいチーム メンバーがコンポーネントの構造を理解しようとしている場合でも、TypeScript は追加のドキュメント レイヤーとして機能します。 リファクタリングへの自信: リファクタリングが怖いですか? TypeScript があなたをサポートします。コード内でのコントラクトを保証する型を使用すると、リファクタリング段階で多くの潜在的なエラーが検出され、プロセスの困難が軽減されます。 コミュニティとエコシステム: TypeScript を採用すると、繁栄するエコシステムへの扉が開きます。 DefinitelyTyped の型付きライブラリから、コミュニティ フォーラムでの無限のサポート、より合理化されたサードパーティ パッケージの統合まで、あなたは良い仲間です。 学習曲線: はい、TypeScript には学習曲線が導入されています。おそらくイライラしたり、型やインターフェイスに関して混乱したり、コンパイラと格闘したりする瞬間があったでしょう。しかし、これまでの道のりを振り返ってみると、コードとその動作をどれほど理解できるようになったのかがわかります。
featured image - React プロジェクトを JavaScript から TypeScript に移行する方法
Leandro Nuñez HackerNoon profile picture
0-item


目次

  • 導入

  • なぜ移行するのか?メリットを理解する

  • 始める前に: 前提条件

  • 移行の開始: プロジェクトでの TypeScript のセットアップ

  • React コンポーネントのリファクタリング

  • 状態管理とコンテキスト API

  • ルーティングと非同期操作

  • TypeScript でのテスト

  • 非 TypeScript パッケージの処理

  • ベストプラクティスとよくある落とし穴

  • 結論

  • 追加リソース



導入

こんにちは、開発者の皆さん! React プロジェクトでJavaScriptからTypeScriptへの移行を検討する準備ができている皆さんにお会いできて大変うれしく思います。


JavaScript を使ったことがある人なら、それが履き心地の良い古い靴のようなものであることをご存知でしょう。少しすり減っていて、時々予測不能ですが、馴染みのあるものです。ただし、TypeScript は、カスタム インソールで靴をアップグレードするようなものです。同じウォーキング体験ですが、サポートが追加されています。


では、TypeScript に関する話題は何でしょうか?


これは本質的には JavaScript ですが、追加機能が多数組み込まれており、最も重要なのは型チェックです。


厄介なundefined is not a functionを想像してください。 TypeScript があなたの生活にもたらすのは、まさにそのような平安です。


このガイドでは、TypeScript を React プロジェクトに統合する理由と方法を説明します。


なぜ反応するのか?それは明らかに素晴らしいし、私たちがそれを愛しているからです。また、React のコンポーネントベースのアプローチと TypeScript の型チェック機能を組み合わせることで、非常に効率的で楽しいコーディング エクスペリエンスが実現します。


TypeScript をプロジェクトに追加する様子を少しだけ見てみましょう。典型的な JavaScript コンポーネントでは、次のようになります。

 // JavaScript way function Greeting({ name }) { return <h1>Hello, {name}</h1>; }


TypeScript では、 nameが常に文字列として扱われるようにする方法を導入しています。

 // TypeScript style type Props = { name: string; }; function Greeting({ name }: Props) { return <h1>Hello, {name}</h1>; }


type Props部分に注目してください


これは、TypeScript が「監視しています。 name文字列であることを確認したほうがよいでしょう」と伝える方法です。これは単純な変更ですが、大きな影響を及ぼします。これで、守護天使が型関連のバグを積極的に防止し、コードをより堅牢かつ予測可能にすることができました。


しかし、それはほんのわずかな垣間見るだけです。 TypeScript には膨大なメリットと実践方法があり、それをこの包括的なガイドで明らかにします。環境のセットアップから、コンポーネントやプロップのリファクタリング、さらにはよくある落とし穴を回避するためのベスト プラクティスに至るまで、取り上げるべきことがたくさんあります。さあ、シートベルトを締めて、このショーをスタートさせましょう!




なぜ移行するのか?メリットを理解する

特にReactプロジェクトで JavaScript から TypeScript への移行を検討している場合、「本当に苦労する価値があるのだろうか?」と疑問に思うのはあなただけではありません。プロジェクト全体の言語を移行するのは簡単な作業ではありません。それには努力と学習が必要で、最初は生産性が少し低下します。では、開発者はなぜ切り替えを行うのでしょうか?説得力のある理由を分析してみましょう。


1. エラーをより早くキャッチする: 静的型チェック

TypeScript の中核的な機能は、静的型システムです。動的に型指定される JavaScript とは異なり、TypeScript では変数、関数パラメーター、および戻り値の型を指定できます。特典は何ですか?エラーは、コードが運用環境に近づくずっと前に、開発中に検出されます。


簡単な例を考えてみましょう。

 // In JavaScript function createGreeting(name) { return `Hello, ${name}`; } // You might not catch this typo until runtime const greeting = createGreeting(123); console.log(greeting); // "Hello, 123" - Wait, that's not right!


それでは、TypeScript がどのように役立つかを見てみましょう。

 // In TypeScript function createGreeting(name: string): string { return `Hello, ${name}`; } // TypeScript will flag this immediately - '123' is not a string! const greeting = createGreeting(123);


TypeScript を使用すると、一見無害に見えるバグは即座に捕らえられ、事故が発生した瞬間に確実に気づくことができます。こうすることで、フィードバック ループが短縮され、運用環境で奇妙なバグを見て頭を悩ませることがなくなります。


2. コードの品質と理解しやすさの向上

TypeScript による型指定の強制は、他の開発者 (または将来の開発者) が、関数がどのような種類のデータを期待し、何を返すかを一目で理解できることを意味します。この明確さにより、コードベースがより読みやすくなり、自己文書化されます。


同僚が書いた JavaScript 関数に遭遇したと想像してください。

 function calculateTotal(items) { // ... complicated logic ... }


どのようなitemsあるべきかを理解するには、おそらく関数を詳しく調べるか、関数が使用されている場所を見つける必要があります。 TypeScript を使用すると、次のことがすぐにわかります。

 type Item = { price: number; quantity: number; }; // Now we know exactly what to expect! function calculateTotal(items: Item[]): number { // ... complicated logic ... }


3. 強化されたエディターのサポート

TypeScript は、オートコンプリート、リファクタリング、およびデバッグを改善してテキスト エディターと IDE を強化することで、開発者のエクスペリエンスを新しいレベルに引き上げます。 TypeScript はコードの理解をエディターと共有できるため、この統合が可能です。

これは、エディターがメソッド名を提案したり、関数パラメーター情報を提供したり、関数の誤った使用法について警告したりするときに発生します。これは、追加の安全層を備えたコードのナビゲートを支援する副操縦士がいるようなものです。


4. コラボレーションが容易になる

チーム環境では、TypeScript はコードベース全体に特定の標準と構造を強制するのに役立ちます。複数の開発者がプロジェクトに貢献する場合、TypeScript の厳格なルールにより、全員が同じコーディング ガイドラインに従うことが保証され、共同作業がよりスムーズになります。これは、全体的に「品質と一貫性」を語る共通言語です。


5. コードの将来性を保証する

JavaScript は進化しており、TypeScript は最新の機能に対応することを目指しています。 TypeScript を使用すると、次世代の JavaScript 機能が主流に採用される前に利用を開始でき、プロジェクトを最新かつ最先端の状態に保つことができます。


結論として、TypeScript への移行は、単にエラーを早期に検出することではありません。それはコーディング プロセスを総合的に改善することです。チーム コラボレーションの向上からプロジェクトの将来性の確保まで、TypeScript は、信頼性が高く、スケーラブルで、保守可能なアプリケーションを構築するための堅牢な基盤を提供します。


切り替えは最初は気が遠くなるように思えるかもしれませんが、上で説明した利点を考慮すると、TypeScript が世界中の多くの開発者にとってお気に入りになっている理由は明らかです。飛び込む準備はできていますか?続けましょう!



始める前に: 前提条件

さて、React プロジェクトで TypeScript に切り替える準備は完了しましたか?素晴らしい決断です!


ただし、実際のプロセスに入る前に、いくつかのことが整っていることを確認する必要があります。

これを準備段階と考えてください。移行プロセスがバターのようにスムーズになるように、すべてのツールを準備します。


準備する必要があるものは次のとおりです。

1. 既存の React プロジェクト

まず最初に、既存の React プロジェクトが必要です。このプロジェクトは、あなたが気軽に実験できるプロジェクトであるはずです。移行プロセスは非常に簡単ですが、一時的に混乱しても大丈夫な環境でこれを実行することをお勧めします。


 // Here's a simple React functional component in your project export default function Greeting({ name }) { return <h1>Hello, {name}!</h1>; }


このコンポーネントは出発点として適しています。機能的でクリーンで、何が起こっているかが一目でわかります。

2. TypeScript の基本的な理解

TypeScript の専門家である必要はありませんが、基本を理解していれば、この移行は非常に簡単になります。


型とインターフェイスの定義方法を理解し、 typeinterfaceの違いを理解します。

ちょっとした宿題は大いに役立ちます、信じてください。


 // A sneak peek into TypeScript syntax type Props = { name: string; // defining the 'name' expected to be a string }; // Your component in TypeScript would look like this import React, { FC } from 'react'; interface GreetingProps { name: string; } const Greeting: FC<GreetingProps> = ({ name }) => { return <h1>Hello, {name}!</h1>; } export default Greeting;


違いを見ます?現在、 Greeting何を期待しているのかを明確にし、コンポーネントをより予測可能にし、操作しやすくしています。


3. ノードとNPM/Yarn

パッケージの処理にはnpmまたはyarnを使用するため、開発環境には Node.js がインストールされている必要があります。 React を使用しているため、この要件は当然のことですが、確認しておいて損はありません。


 # Check if Node is installed node --version # Check if npm is installed npm --version # Or for yarn yarn --version


ターミナルにはこれらのツールの現在のバージョンが表示され、すべてがセットアップされ、使用できる状態になっていることが確認されます。


4. コードエディタ

TypeScript を適切に処理できるコード エディターが必要になります。 Visual Studio Code は、堅牢な TypeScript サポートが組み込まれており、インテリジェントなコード補完とエラーの強調表示により開発プロセスをよりスムーズにするため、多くの人に人気があります。


5. バージョン管理

この手順は必須ではありませんが、賢明な手順です。現在のプロジェクトが git でバージョン管理されていることを確認してください。何か問題が発生した場合は (ただし、問題が発生しないように努めます)、スリープ状態を失わずに、いつでも前のバージョンに戻すことができます。


 # Check if git is installed git --version # If not, you need to initialize version control before proceeding git init git add . git commit -m "Pre-TypeScript commit"


このセーフティネットがあると、背中が覆われていることを確認して、自信を持って実験できることを意味します。


前提条件については以上です。プロジェクトが完成し、TypeScript をいくつかブラッシュアップし、環境の準備が整い、セーフティ ネットが整いました。


これで、移行プロセスに入る準備がすべて整いました。ボールを転がしてみましょう!



移行の開始: プロジェクトでの TypeScript のセットアップ React コンポーネントのリファクタリング

よし、次のフェーズへ!


TypeScript の準備は完了しましたが、今度は自分の手を汚す必要があります。


React コンポーネントをリファクタリングする時期が来ました。この手順には、単にファイル拡張子を変更するだけではありません。より堅牢でエラーのないコーディング エクスペリエンスを実現するには、コンポーネント コードを更新して TypeScript の機能を利用する必要があります。

飛び込んでみましょう!


1. ファイル拡張子の変更

まず最初に、コンポーネント ファイルの名前を変更しましょう。このプロセスには、JSX コードを含むファイルの拡張子を.jsから.tsxに変更することが含まれます。


コマンド ラインからプロジェクトのソース ディレクトリでこれを一括で実行する方法は次のとおりです。

 # For Unix-like shells, navigate to your source folder and run: find . -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.tsx"' {} \; # If you're using PowerShell (Windows), navigate to your source folder and run: Get-ChildItem -Filter *.js -Recurse | Rename-Item -NewName { $_.Name -replace '\.js$','.tsx' }


これらのコマンドは、プロジェクトのソース ディレクトリ内のすべての.jsファイルを検索し、それらの名前を.tsxに変更します。これはファイルに「TypeScript の世界へようこそ!」と伝えるようなものです。


2. コンポーネントの入力

ファイルの名前を変更したら、コードに取り組みましょう。 JavaScript の単純な機能コンポーネントから始めます。

 // Before: MyComponent.js import React from 'react'; function MyComponent({ greeting }) { return <h1>{greeting}, world!</h1>; }


ここで、TypeScript を使用できるようにこれをリファクタリングしましょう。

 // After: MyComponent.tsx import React, { FC } from 'react'; // Define a type for the component props interface MyComponentProps { greeting: string; } // Use the 'FC' (Functional Component) generic from React, with our props type const MyComponent: FC<MyComponentProps> = ({ greeting }) => { return <h1>{greeting}, world!</h1>; }


私たちはここで何をしましたか?


コンポーネントの props を記述するインターフェイスMyComponentPropsを定義し、型の安全性を確保しました。 greeting文字列であると言うことで、たとえば代わりに数字を渡そうとすると、TypeScript は怒鳴ります。また、React の型定義のFC型 ( Functional Componentの略) を使用して、TypeScript がそれが React コンポーネントであることを認識できるようにしました。


3. useState と useEffect を厳密に型指定する

機能コンポーネントの共通機能である状態と効果にタイプを追加して、コンポーネントをさらにアップグレードしてみましょう。


状態と効果を含むコンポーネントは次のとおりです。

 // Before: Counter.js import React, { useState, useEffect } from 'react'; function Counter() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }


これに TypeScript の魔法を少し加えてみましょう。

 // After: Counter.tsx import React, { useState, useEffect, FC } from 'react'; const Counter: FC = () => { // Declare the 'count' state variable with TypeScript const [count, setCount] = useState<number>(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(prevCount => prevCount + 1)}> Click me </button> </div> ); }


リファクタリングされたコンポーネントでは、 count状態にnumberを期待するように TypeScript に明示的に指示しました。


この詳細により、予期した数値の代わりに文字列、オブジェクト、または天が禁じているnull誤って入力してしまう可能性がある厄介なバグを防ぎます。


そして、行きます!


TypeScript を使用するように React コンポーネントをリファクタリングすることに成功しました。コンポーネント、状態、プロパティを明示的に入力することで、より予測可能で保守しやすいコードベースを作成できます。私たちはただコーディングしているだけではありません。私たちはそれに値する精度を備えた傑作を作り上げています。


次は、より複雑なシナリオと、TypeScript がどのように役立つのかをさらに詳しく見ていきます。



状態管理とコンテキスト API

ここで、TypeScript を使用した React における状態管理の核心に触れてみましょう。 JavaScript プロジェクトで Context API を使用したことがある場合は、これが、すべてのレベルで手動で props を渡すことなく、コンポーネント ツリーを通じてデータを渡すための強力な機能であることをご存知でしょう。 TypeScript では、厳密な型付けの追加の利点が得られ、コンテキスト データがさらに堅牢で予測可能になります。


飛び込む準備はできていますか?さあ行こう!


1. 型付きコンテキストの作成

まず、TypeScript を使用して新しいコンテキストを作成します。このコンテキストにより、デフォルト値、プロバイダー値、またはコンシューマー コンポーネントが期待される型と一致することが保証されます。


JavaScript で基本的なコンテキストを定義する方法は次のとおりです。

 // Before: DataContext.js import React, { createContext, useState } from 'react'; export const DataContext = createContext(); export const DataProvider = ({ children }) => { const [data, setData] = useState(null); return ( <DataContext.Provider value={{ data, setData }}> {children} </DataContext.Provider> ); };


次に、TypeScript を使用してこのコンテキストを入力してみましょう。

 // After: DataContext.tsx import React, { createContext, useState, FC, ReactNode } from 'react'; // First, we define a type for our context's state interface DataContextState { data: any; // Tip: Replace 'any' with the expected type of 'data' setData: (data: any) => void; // And here too, replace 'any' with the actual expected type } // We ensure our createContext() call is typed with the above interface export const DataContext = createContext<DataContextState | undefined>(undefined); // Now, let's create a provider component export const DataProvider: FC<{children: ReactNode}> = ({ children }) => { const [data, setData] = useState<any>(null); // Again, consider replacing 'any' with your actual data type // The context provider now expects a value that matches 'DataContextState' return ( <DataContext.Provider value={{ data, setData }}> {children} </DataContext.Provider> ); };


ここで行ったことは、コンテキスト データを厳密に型指定する TypeScript インターフェイスDataContextStateを作成することです。また、 createContext関数とDataProviderコンポーネントも型付けし、状態変数からコンテキスト値までのすべてが定義された型と一致していることを確認します。


2. 入力されたコンテキストの使用

型指定されたDataContextが完成したので、それをコンポーネント内でどのように利用できるかを見てみましょう。


useContextフックを使用する必要があります。その方法は次のとおりです。

 // ComponentUsingContext.tsx import React, { useContext, FC } from 'react'; import { DataContext } from './DataContext'; const ComponentUsingContext: FC = () => { // Here we're telling TypeScript to expect 'DataContextState' from our context const { data, setData } = useContext(DataContext) ?? {}; // This function would update the context state, triggering re-renders in consuming components const handleUpdateData = () => { const newData = { message: "Hello, TypeScript!" }; // This should match the structure of your data type setData(newData); }; return ( <div> <pre>{JSON.stringify(data, null, 2)}</pre> <button onClick={handleUpdateData}>Update Data</button> </div> ); };


ComponentUsingContextでは、コンテキストにアクセスし、値がDataContextStateと一致することを TypeScript が検証することを期待しています。 handleUpdateData関数は、共有状態を更新する方法を示していますDataContextを使用するコンポーネントは、 setDataが呼び出されたときに新しいデータで再レンダリングされます。


Context API で TypeScript を使用することで、共有状態管理がアプリケーション全体で一貫しているという確信が得られます。コンパイラは、コンテキストが提供するものとコンポーネントが期待するものとの間の矛盾を検出します。この相乗効果により、コードの信頼性が高まり、開発プロセスがよりスムーズになり、他の方法で遭遇する可能性のあるバグのカテゴリー全体を回避できるようになります。


引き続き頑張ってください。少し入力するだけで、後で多くのデバッグを節約できることを覚えておいてください。



TypeScript でのルーティングと非同期操作のテスト >

TypeScript が React アプリケーションのさまざまな側面をどのように改善するかを見てきました。次は、もう 1 つの重要な領域であるテストについて説明します。


テストはアプリが期待どおりに動作することを確認するための基本であり、TypeScript を使用するとテストの信頼性と効率を高めることができます。 TypeScript がテスト、特に React プロジェクトでどのような役割を果たすかを詳しく見てみましょう。


1. テストの準備を整える

コードに入る前に、React プロジェクトでのテストに必要なライブラリがインストールされていることを確認してください。ここでは、React アプリケーションのテストに広く使用されている Jest と React Testing Library を使った簡単なセットアップを示します。

 npm install --save-dev jest @types/jest @testing-library/react @testing-library/jest-dom


これらのライブラリは、単体テストと統合テストを作成するための堅牢な環境を提供します。ここで、わかりやすくするために現実世界のシナリオを考えてみましょう。


2. 現実世界のテスト シナリオ: ユーザー グリーティング コンポーネント

時刻に基づいてユーザーに挨拶する単純なコンポーネントがアプリにあると想像してください。これは、ユーザーの名前を小道具として、現在時刻を状態として受け取る機能コンポーネントです。


UserGreetingコンポーネントは次のようになります。

 // UserGreeting.tsx import React, { FC, useState, useEffect } from 'react'; interface UserGreetingProps { name: string; } const UserGreeting: FC<UserGreetingProps> = ({ name }) => { const [currentHour, setCurrentHour] = useState(new Date().getHours()); const [greeting, setGreeting] = useState(''); useEffect(() => { // Determine the time of day and set the appropriate greeting if (currentHour < 12) { setGreeting('Good morning'); } else if (currentHour < 18) { setGreeting('Good afternoon'); } else { setGreeting('Good evening'); } }, [currentHour]); return ( <div> <h1>{greeting}, {name}!</h1> </div> ); } export default UserGreeting;


ここで、コンポーネントがさまざまな条件下で期待どおりに動作することを確認するテストを作成する必要があります。私たちのテスト ケースでは、時刻に基づいて適切な挨拶が表示されることを確認します。


Jest および React テスト ライブラリを使用してこれらのテストを作成する方法は次のとおりです。

 // UserGreeting.test.tsx import React from 'react'; import { render, screen } from '@testing-library/react'; import UserGreeting from './UserGreeting'; describe('UserGreeting Component', () => { // Mock date for consistent testing const originalDate = Date; beforeAll(() => { const mockDate = new Date(2023, 10, 17, 14); // 2:00 PM global.Date = jest.fn(() => mockDate) as any; }); afterAll(() => { global.Date = originalDate; // Restore original Date object }); it('displays the correct greeting for the afternoon', () => { render(<UserGreeting name="Jordan" />); // Assert the greeting based on the mocked time of day expect(screen.getByText('Good afternoon, Jordan!')).toBeInTheDocument(); }); // Additional tests would repeat this process for other times of day, // ensuring our component behaves consistently. });


このスクリプトでは、設定された時間 (午後 2 時をモック) でコンポーネントをレンダリングし、期待どおりに「こんにちは」が出力されるかどうかを確認しています。コンポーネントが完全にカバーされていることを確認するために、他の時間帯 (朝、夕方) にさらにテストを作成できます。


TypeScript を通じて、テストでコンポーネントに渡す props が期待される型と一致していることを確認します。このようにして、テストで偽陰性を引き起こす可能性のある不適切なプロパティによる問題の発生を回避し、テストの堅牢性と信頼性を確保します。


テストで TypeScript を使用すると、開発プロセスの早い段階で問題を発見するのに役立ち、アプリがより堅牢で保守しやすくなります。それはwin-winの状況です!一貫性のある包括的なテストは、高品質のソフトウェア開発の特徴であることを忘れないでください。それを維持する!




非 TypeScript パッケージの処理

さて、React プロジェクトで TypeScript に移行するときによくつまずく領域、つまり TypeScript で書かれていない JavaScript ライブラリとパッケージの処理に取り組んでみましょう。これは一般的なシナリオです。 TypeScript プロジェクトを立ち上げて実行し、サードパーティのパッケージをインストールすると、TypeScript コンパイラが問題を抱えていることがわかります。心配しないで;解決策はあります。


1. 問題に遭遇する

典型的なシナリオは次のとおりです。標準で TypeScript をサポートしていないパッケージを使用しようとすると、TypeScript コンパイラが「モジュール 'モジュール名' の宣言ファイルが見つかりませんでした」のようなエラーをスローし始めます。おなじみですね?


この問題は、TypeScript がライブラリとパッケージの構造を理解するために型定義に依存しているために発生します。これらの型定義が欠落している場合、TypeScript は少し失われます。しかし、心配しないでください。私たちはこれに対処する戦略を持っています。

2. DefinitelyTyped の使用

最初にできることの 1 つは、コミュニティが DefinitelyTyped 経由でパッケージの型定義を提供しているかどうかを確認することです。 DefinitelyTyped は、コミュニティによって維持されている型定義の大規模なリポジトリです。


DefinitelyTyped の型を確認して使用する方法は次のとおりです。


  1. npm を使用してパッケージのインストールを試行し、パッケージの型定義を検索します。 DefinitelyTyped の型定義には通常、 @types/という接頭辞が付けられます。
 npm install @types/package-name


たとえば、 lodashライブラリを使用している場合は、次を実行します。

 npm install @types/lodash


  1. インストール後、プロジェクト内のどこにもタイプを明示的にインポートする必要はありません。 TypeScript はそれらを自動的に検出して使用するため、通常どおりライブラリをインポートして使用し、オートコンプリートと型チェックを行うことができます。


しかし、DefinitelyTyped で利用可能な型定義がない場合はどうなるでしょうか?


3. 独自の宣言ファイルの作成

DefinitelyTyped に必要な型定義がない場合は、カスタム宣言ファイルを作成します。このアプローチにはより多くの労力が必要ですが、TypeScript プロジェクトが JavaScript ライブラリでスムーズに動作することが保証されます。


ここでは、実行できることの簡略化したバージョンを示します。


  1. プロジェクトのソース (またはtypes ) ディレクトリ内に.d.ts拡張子を持つ新しいファイルを作成します。これは、 declarations.d.tsようなものになる可能性があります。


  2. このファイルでは、モジュールを宣言し、場合によってはライブラリに期待される基本構造の概要を説明する必要があります。例えば:

 // This is a simplistic type declaration file for a hypothetical package. // We declare the module so TypeScript recognizes it. declare module 'name-of-untyped-package' { // Below, we're declaring a very basic structure. It's saying // there's a function we're expecting to exist, which returns any. // Ideally, you'd want to flesh this out with more specific types // if you know them or as you learn more about the library. export function functionName(arg: any): any; // You can continue to define the shapes of other functions or variables // you expect to exist within the package. The more detailed you are here, // the more helpful your type checking will be. }


この自家製の宣言ファイルは型定義の完全なセットほど包括的ではありませんが、TypeScript に「信じてください、このモジュールが存在し、これらの関数/変数を提供することは知っています。」と伝えます。ここから、必要に応じてさらに詳細な定義を構築できます。


非 TypeScript パッケージを扱うのは少しハードルが高いことを覚えておいてください。しかし、これらの戦略により、TypeScript プロジェクトが堅牢な状態を維持し、私たちが求めている型の安全性と予測可能性を確実に享受できるようになります。重要なのは、コードベースに対する自信です。



ベストプラクティスとよくある落とし穴

React プロジェクトで TypeScript に切り替えることは、ファイル拡張子を変更したり型アノテーションを追加したりするだけではありません。また、一般的な障害を回避しながら、TypeScript が提供する機能を最大限に活用するために考え方と開発実践を適応させることも重要です。そこで、この過程で遭遇する可能性のあるいくつかのベスト プラクティスと一般的な落とし穴について説明します。

1. ベストプラクティス

1.1 型推論を重視する

すべてに注釈を付けたくなるかもしれませんが、TypeScript の強みの 1 つは型推論です。多くの場合、コードのすべての部分に明示的な型を追加する必要はありません。

 // Instead of this: let x: number = 0; // You can rely on type inference: let x = 0; // TypeScript knows this is a number

アノテーションを過剰に追加すると、付加価値が得られずにコードが冗長になってしまう可能性があります。 TypeScript を信頼して、可能な場合には型を推論します。

1.2 ユーティリティタイプの採用

ユーティリティ型は、さまざまなシナリオで型を処理する柔軟な方法を提供します。これらにより、多くの労力が節約され、型処理がより効率的になります。

 // Example of using Partial to make all properties in an object optional function updateProfile(data: Partial<UserProfile>) { // function implementation } // Now you can pass only the parts of UserProfile you need to update updateProfile({ username: "newUserName" }); // This is valid

PartialReadonlyPick 、およびその他のユーティリティ タイプは非常に便利です。

1.3 既知の定数セットに列挙型を使用する

特定の値のみを取るプロパティがある場合、 enumを使用すると、それらの値の検証を提供しながら意図を明確にすることができます。

 enum UserRole { Admin = 'ADMIN', User = 'USER', Guest = 'GUEST', } // Now UserRole can only be one of the values defined in the enum function assignRole(role: UserRole) { // function implementation }

1.4 オブジェクト構造定義のインターフェイスを優先する

多くの場合、 typeinterface同じ意味で使用できますが、オブジェクトまたはクラスの構造を定義するためにinterface使用すると、コードが読みやすくなり、より適切なエラー メッセージが表示されます。

 interface UserProfile { username: string; email: string; // More properties... }


2. よくある落とし穴

2.1 anyの使用

any使用すると、型チェックがバイパスされるため、TypeScript の利点が無効になります。これは簡単な修正のように思えるかもしれませんが、コードの安全性と予測性が低下します。

 // Try to avoid this: let userData: any = fetchData(); // Instead, define a type for the data you expect: let userData: UserProfile = fetchData();

2.2 コンパイラ警告の無視

TypeScript のコンパイラ警告が役に立ちます。これらを無視すると、TypeScript を使用して回避しようとしているのと同じ種類のバグや問題が発生する可能性があります。

2.3 複雑な型で迷う

場合によっては、開発者は型を正確にしようとして、理解や維持が難しい非常に複雑な型定義を作成することがあります。型が複雑になっている場合は、コードを簡素化するかリファクタリングする必要があるかもしれません。

2.4 サードパーティのライブラリの種類を忘れる

サードパーティのライブラリを使用している場合は、DefinitelyTyped に既存の TypeScript タイプがあるかどうかを常に確認してください。そうしないと、これらのライブラリのタイプ セーフティ機能が失われる可能性があります。

結論として、TypeScript の採用は、単に新しい構文を使用するだけではありません。それは、エラーを回避し、コードを読みやすくし、メンテナンスを改善するのに役立つ新しいプラクティスを採用することです。よくある罠を避けてください。目標は、よりクリーンで信頼性が高く、保守しやすいコードを作成することであることを忘れないでください。




結論

さて、皆さん、TypeScript への移行の旅は終わりに達しました。なかなか大変でしたね。私たちは「なぜ」という大きな疑問から始めて、実際に React プロジェクトを JavaScript から TypeScript に移行するという核心を掘り下げました。 TypeScript 環境のセットアップから、コンポーネントのリファクタリング、状態の管理、ルートの処理、さらには厄介な非 TypeScript パッケージの処理に至るまで、多くの分野をカバーしてきました。


この過程を振り返ると、TypeScript への移行は、 .jsファイルを.tsxで単に「検索して置換」するだけではないことがわかります。これは、新しい規則を学び、型を深く理解し、そして最も重要なことに、コードの信頼性と一貫性についての考え方を変えることを伴う戦略的な動きです。


最後にいくつかの要点を示します。

  1. セーフティ ネット: TypeScript はプロジェクトにセーフティ層を導入し、実行時に大混乱を引き起こす前にエラーを検出します。このセーフティ ネットは、一度慣れてしまえば、コードに対する信頼性と全体的な開発速度の面で大きな変化をもたらします。


  2. より明確な通信: 型を使用すると、コードはより明示的に通信できるようになりました。コードを再検討している場合でも、新しいチーム メンバーがコンポーネントの構造を理解しようとしている場合でも、TypeScript は追加のドキュメント レイヤーとして機能します。


  3. リファクタリングへの自信: リファクタリングが怖いですか? TypeScript があなたをサポートします。コード内でのコントラクトを保証する型を使用すると、リファクタリング段階で多くの潜在的なエラーが検出され、プロセスの困難が軽減されます。


  4. コミュニティとエコシステム: TypeScript を採用すると、繁栄するエコシステムへの扉が開きます。 DefinitelyTyped の型付きライブラリから、コミュニティ フォーラムでの無限のサポート、より合理化されたサードパーティ パッケージの統合まで、あなたは良い仲間です。


  5. 学習曲線: はい、TypeScript には学習曲線が導入されています。おそらくイライラしたり、型やインターフェイスに関して混乱したり、コンパイラと格闘したりする瞬間があったでしょう。しかし、これまでの道のりを振り返ってみると、コードとその動作をどれほど理解できるようになったのかがわかります。


TypeScript への移行はスプリントではないことに注意してください。それはマラソンです。最初はいくつかのハードルがあるかもしれませんが、長期的にはコードの品質、予測可能性、保守性が向上するため、努力する価値は十分にあります。


開発の旅を続けながら、TypeScript を探索、学習し、経験を共有し続けてください。あらゆる挑戦は学びの機会です。将来のあなた (そしてあなたのチーム) は、あなたが現在開発している、堅牢でタイプセーフで保守性が大幅に向上したコードベースに感謝するでしょう。


React を使用した TypeScript の探索にご参加いただきありがとうございます。コーディングを続け、改善を続け、そして最も重要なことに、プロセスを楽しむことです。


つながりを保つ

この記事を気に入っていただき、Web 開発についてさらに詳しく知りたい場合は、さまざまなプラットフォームでお気軽にご連絡ください。

開発者へ

ハッカーヌーン.com

ハッシュノード.com

ツイッター.com


フィードバックやご質問はいつでも大歓迎です。

学習、コーディング、素晴らしい Web アプリケーションの作成を続けてください。


コーディングを楽しんでください!



追加リソース

このガイドは終了しましたが、TypeScript の冒険はここで終わりません。 TypeScript の世界は広大で、探索し、学び、貢献できるリソースが豊富にあります。以下は、理解を深め、TypeScript コミュニティの最新情報を維持するのに役立つ貴重なリソースの一部です。


  1. TypeScript 公式ドキュメント: TypeScript を探索するには、公式 Web サイトほど適した場所はありません。さまざまな機能に関する詳細なドキュメント、例、説明が満載です。


  2. DefinitelyTyped : サードパーティのライブラリを使用する場合、 DefinitelyTypedは救世主です。これは、高品質の TypeScript 型定義の大規模なリポジトリです。


  3. React TypeScript チートシート: この包括的なチートシートは、 TypeScript に移行する React 開発者に特化しており、一般的なパターンと実践方法をカバーしています。


  4. TypeScript Deep Dive : TypeScript の詳細な探索を提供する優れたオンライン書籍です。 Deep Dive では、実践的なシナリオに焦点を当てて TypeScript の核心を説明します。


  5. TypeScript GitHub リポジトリ:公式 TypeScript GitHub リポジトリにアクセスして、コミュニティに参加し、TypeScript の最新開発情報を入手してください。


  6. Stack Overflow : Stack Overflowの TypeScript タグは、世界中の開発者が遭遇する一般的な (そして珍しい) クエリと微妙なユースケースのハブです。それは実践的な洞察の宝庫です。


  7. TypeScript Weekly : 厳選されたニュースレターであるTypeScript Weekly は、最新の記事、ヒント、リソースを直接受信トレイに配信します。


  8. Reddit と Discord チャネル: Reddit の r/typescriptやさまざまな Discord チャネルなどのプラットフォーム上のコミュニティでは、TypeScript に関連する活発なディスカッション、ニュース、問題解決スレッドがホストされています。


  9. 公式 TypeScript ブログ: TypeScript チームからのお知らせ、詳細、チュートリアルについては、公式ブログをチェックしてください。


  10. オンライン コーディング プラットフォーム: CodecademyfreeCodeCampScrimbaなどのプラットフォームを通じたインタラクティブな学習体験により、実践的な TypeScript コースが提供されます。


コミュニティは参加によって繁栄するということを忘れないでください。遠慮せずに質問したり、回答を投稿したり、解決策や経験を共有したりしてください。コミュニティ フォーラム、公式ドキュメント、継続的な練習の集合的な知恵が、TypeScript の習得に向けて導きます。


コーディングを楽しんでください!