1・はじめに
私がReactの開発にTypescriptを導入するようになってしばらく経ちましたが、Reactの開発にTypescriptを導入することはメリットが多くあると感じますので、皆さんにも共有したいと思います。
今回の例で使用したコードをGithubにもアップしましたので、この記事を見ながらご自分で試してみる等有効活用していただけたら嬉しいです。
今回使用したコード
2・React+Typescriptのメリット
・トランスパイルする前にエラーを表示してくれる
Typescriptは静的型付け言語であり、変数等に予め型を定義する必要があります。
これはReactにTypescriptを使用する時も例外ではなく、Reactの**「props」**と呼ばれるコンポーネント間で受け渡す任意の値や、コンポーネント内で使用する関数にも事前に型を定義する必要が出てきます。
予め定義をすることで、渡されるはずの値が渡されていないときや、渡される値の型が間違っていた時に「プログラム実行前」にエラーを起こして警告してくれるようになります。
import { VFC } from 'react'
interface SampleProps {
number: number; //必須項目
string: string; //必須項目
boolean?: boolean //必須ではない
}
const Sample1: VFC<SampleProps> = (props) => {
return (
<>
<h2>プロップスの候補表示</h2>
<div>number is {props.number}</div>
<div>string is {props.string}</div>
<div>boolean is {props.boolean}</div>
</>
);
}
export default Sample1;
例では「Sample」というコンポーネントを作成し、それぞれ必須項目としてnumber
、string
、必須ではなく任意でboolean
というpropsを受け取るよう設定しました。
ここでインターフェースSampleProps
からnumber
の定義を消去してみると、
Typescriptに怒られてしまいましたね。これはSampleProps
にnumber
という値は定義されていないよ!ということです。
import React from 'react';
import Sample from './component/Sample';
function App() {
return (
<>
<Sample1
number={1}
string={'サンプル'}
/>
</>
);
}
次の例では、app.tsx
で先程定義したコンポーネントを使用し、props
に必要な値を渡しています。
先程定義したコンポーネントSample
では、number
、string
は必須になっていました。試しに渡していた2つのpropsを消去してみると、
このようにインターフェースSampleProps
で必須項目に指定してたnumber
、string
がありませんよ!としっかり警告を出してくれます。
boolean
は?
を付与して「必須項目ではない」ということを定義していましたので、値が渡されなくても警告は出ません。
また、propsに定義していた型とは違う型の値を渡すと、
これもTypescriptがしっかり警告を出してくれました。
このようにTypescriptによって事前に型定義をすることで、型安全になるだけではなく**「propsに値を渡し忘れた」**などのヒューマンエラーもプログラム実行前にリアルタイムで検出してくれるため、効率良くコードを記述できるようになります。
・候補表示(コードサジェスチョン)
Typescriptを使用して型定義をすると、IDEのインテリセンス機能によってインターフェース、型定義ファイルに記述されている値、メソッド等が候補として表示されるようになります。
先程のSample
コンポーネントを例に出すと、インターフェースSampleProps
にて定義した値が候補として表示されるようになります。
画像の通り、「props.」と入力したらインターフェースで定義された値が候補に表示されているのがわかりますね。
const submitSampleForm = (e: FormEvent) => {
e.preventDefault();
console.log(variables);
}
次の例は、フォーム実装する時によくある、onSubmitイベントが発生した場合の処理を簡単に記述した関数です。
例では、引数eに@types/reactという型定義ファイル(事前にインストールしています)の中の「FormEvent」という型を使用しています。それによって、FormEventで定義されている値、メソッド等が候補に表示されます。
・関数がドキュメントのようになる+参照できる
Typescriptを使用し型を定義することによって、自作の関数、ライブラリで用意されている関数の引数、戻り値の型が参照できるようになります。
export const sampleFunction = (a: number, b: number): number => {
return a + b;
};
例では引数にnumber型を取るa
、b
、戻り値にはnumber
型を返すsampleFunction
という関数を定義しました。
この関数を呼び出して関数にカーソルを合わせるだけで、関数の引数、戻り値の型を簡単に確認することができます。
この機能は自作の関数はもちろんライブラリで定義されている関数を使用する時には大変便利で、カーソルを合わせて引数や戻り値を見ればどういう風に関数を使えばよいかわかるほか、ライブラリによっては型定義ファイルにコメントで関数の機能を詳細に説明してくれていることがあり、関数にカーソルを合わせると引数や戻り値とともにそのコメントも表示されるので、いちいちライブラリのドキュメントを見て確認することが減ります。
また、ctrl(command)+左クリックすれば関数やコンポーネントの定義元まで飛ぶこともできます。
画像はSample
コンポーネントでctrl(command)+左クリックしてSampleコンポーネントの定義元を参照しています。
このようにTypescriptを使用し型を定義するorライブラリの型定義ファイルをインストールすると、開発者にとってメリットが大きいことがわかります。
3・メリットは分かった。でも・・・?
・Typescriptって難しいんじゃないの??
これは個人によって難易度の感じ方は変わると思いますが、TypescriptはJavascriptのスーパーセット(上位互換)の言語で、型定義をする部分以外はJavascriptの構文がそのまま使えるので、個人的にはそこまで難易度が劇的に跳ね上がるような感じはありませんでした。静的型付け言語の経験が無い方は最初型定義に苦労するかもしれませんが、やればやるほど自分のコーディングの効率が上がっていることを実感できると思います。
・いちいち全部型定義しなくちゃいけないの??
Typescriptには型推論という素晴らしい機能があり、変数等の前後の文脈から型を推論し自動的に宣言してくれます。
画像はSampleForm
コンポーネントのonChangeイベントで宣言した変数にカーソルを合わせたものです。
eという変数に型を宣言していないのに、Typescriptは適切に型を推論して宣言してくれています。
もちろん全てに型推論が効くわけではありませんが、型推論の機能によって自分が型定義をする機会が減りますので、自分が全て型定義をするということは無いです。
・そこまでガチガチに縛られたくないんだけど・・・・
Typescriptで開発する際はtsconfig.json
という設定ファイルをプロジェクトに置くことが必要になります。
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, .//jsファイルをts.tsxファイルと共存させることができるようになる
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
tsconfig.jsonドキュメント
このファイルにTypescriptにチェックしてもらいたい項目を記述します。
Typescriptを段階的にプロジェクトに導入したい場合は上の例のようにallowJs: true
を設定して.js
と.ts.tsx
ファイルを共存させることもできますし、今よりももっと厳格にチェックして欲しい場合は項目を追加したり、もっと緩くして欲しい場合はstrict: false
にしたり、開発者の要望に沿って柔軟に仕様は変えられるようになっています。
・導入が面倒臭そう・・・・
Reactで新たにプロジェクトを作成する時にcreate-react-app
を用いてプロジェクトを作成するならば、--template typescript
をつけるだけで簡単にプロジェクトにTypescriptを導入できます。
npx create-react-app [任意のプロジェクト名] --template typescript
プロジェクト内にサードパーティのライブラリをインストールする時もライブラリに加えて@types/ライブラリ名
で型定義ファイルをインストールする(ライブラリにビルトインで組み込まれている場合もあり、その場合は型定義ファイルはありません。)だけです。
npm i --save-dev @types/[ライブラリ名]
yarn add -D @types/[ライブラリ名]
たったこれだけで開発者はコード補完等の型定義による恩恵を受けることが可能になります。
4・まとめ
私がReactにTypescriptを導入した時は型定義に苦戦し、「面倒くさくなってるだけじゃん、本当に効率良くなるの?」と思っていましたが、今ではTypescriptがなければ開発したくないほどハマってしまいました(笑)
まだReactにTypescriptを導入したことがない方は是非この機会に導入してみることをお勧めします。