僕がTypeScriptを選ぶわけ

2020.09.11

2021.08.12

Fabeee社員ブログ


 
皆様はじめまして。
ガシラ(@GASHIRA_E)と申します。
フロントエンドエンジニアをやっています。
Reactを使用する時って、jsを使うかtsを使用するか選択肢があると思いますが、僕はtsを使用することが多いです。
僕はjsの自由に書けるところが好きでずっとjsを勉強してたんですが、今はtsが大好きになりました。
僕がtsのどんなところに惚れ込んだのか、皆さんと分かち合いたいと思います。
ハンズオン形式ですので、Node.jsの環境構築とyarnのインストールだけ終われば一緒に学べると思います。
Node.js
yarn
 
 

目次

  1. 1. 環境構築
  2. 2. 設計
  3. 3. 実装準備
  4. 4. jsでの実装
  5. 5. tsでの実装
  6. 6. 総評

1.環境構築

まずは、create-react-appを使用して、react + ts の環境を作成しましょう。

mkdir -p ~/works/
cd ~/works
npx create-react-app ts-is-good --template typescript
cd ts-is-good
yarn start

を実行する事で http://localhost:3000/ にて画面が表示されるようになるはずです。
簡単ですね!
ここまでで環境構築は完了となります。
では、本題の開発時の違いについて学んでいきましょう。
 
 

2. 設計

今回はTODOリストのようなものを作成しましょう!
設計を行います。
ちなみに、今回の設計はファイル分けすぎてもブログが読みにくいので、ブログの読みやすさ優先で行っています。
jsだと、コンポーネントの単位とpropsの受け渡しについては考えるんじゃないでしょうか。

ですが、tsだとpropsに合わせて、型の管理を考えないといけません。

型の管理について考える事でどのようなメリットがあるのか。と言いますと

  1. apiからのレスポンスとComponentの型を揃える事ができる。
  2. 入力が数値なのか、文字列なのかを考える事で、値の扱い方を間違えないようになる。

など、他にもあると思いますが、一旦このくらいとします。
これだけでも、jsとは違って保守性や安全性が高そうなイメージはありますよね。
でも、これまでの過程を見る限り、記述内容が増えるなら実装の時間がかかりそうです。
では、実際に開発する時には実装がどう違うのかを確認していきましょう!
 
 

3. 実装準備

まずは、実装に入る前に準備をしましょう。
src/App.css
他は消してあげてください

label {
  display: flex;
  margin-bottom: 12px;
}
p {
  margin: 0;
}

src/App.tsx

import React from 'react';
import './App.css';
// import JsTodoList from './js/pages/JsTodoList';
// import TsTodoList from './ts/pages/TsTodoList';
import fetchTodoList from './util/fetch/fetchTodoList';
const todoList = fetchTodoList();
function App() {
  return (
    <div>
      <h1>JS</h1>
      {/* <JsTodoList todoList={todoList} /> */}
      <hr/>
      <h1>TS</h1>
      {/* <TsTodoList todoList={todoList} /> */}
    </div>
  );
}
export default App;

そして、データ取得処理をモックで実装しましょう。
src/util/fetch/fetchTodoList.js

const fetchTodo = ()=> {
  // listを取ってくる
  return [
    {
      title: 'true message',
      checked: true
    }, {
      title: 'false message',
      checked: false
    }
  ];
};
export default fetchTodo;

ここまでの準備をすれば

上記のように表示されているはずです。
 
 

4. jsでの実装

さて、本題のjsとtsの比較ですが、まずはjsの実装をやってみましょう。
最初にsrc/App.tsxの修正をしましょう。

import JsTodoList from './js/pages/JsTodoList';
      <JsTodoList todoList={todoList} />

この2行のコメントを解除しましょう。
さて、実装です。
1番小さいコンポーネントの JsTodo.jsx を作成しましょう。
src/js/components/JsTodo.jsx

import React from 'react';
const JsTodo = ({title, checked}) => (
  <li>
    <label>
      <input type="checkbox" checked={checked}/>
      <p>{title}</p>
    </label>
  </li>
);
export default JsTodo;

完成しましたね!
次に一つ上のコンポーネントの JsTodoList.jsxを作成しましょう!

Todoに受け渡すPropsを書いていませんが、エラーが出てくれませんね。
Propsがない状態で実際にビルドして画面を確認すると、コンソールにエラーが表示されています。
エラーに従って修正を進めていくと完成形はこうなります。
src/js/pages/JsTodoList.jsx

import React from 'react';
import JsTodo from '../components/JsTodo';
const JsTodoList = ({todoList}) => {
  return (
    <ul>
      {todoList.map(todo => (
        <JsTodo
          title={todo.title}
          checked={todo.checked}
          key={todo.title}
        />
      ))}
    </ul>
  )
}
export default JsTodoList;

修正するのに、ブラウザとの行き来がめんどくさかったですね。
(onChangeが無いというエラーが出たままですが、すいません!今回放置します。)
さて、続いてtsを書きましょう。
 
 

5. tsでの実装

まずは、src/util/fetch/fetchTodoList.jsfetchTodoList.tsに拡張子を変更しましょう。
そして、データの型を指定しなければいけないので
src/util/fetch/fetchTodoList.ts

import { Todo } from '../../ts/types/Todo';
const fetchTodo = (): Todo[] => {
  // listを取ってくる
  return [
    {
      title: 'true_message',
      checked: true
    }, {
      title: 'false_message',
      checked: false
    }
  ];
};
export default fetchTodo;

このように修正します。
そして、src/App.tsxにて

import TsTodoList from './ts/pages/TsTodoList';

この2行のコメントを解除してあげましょう。
さて、実装に入ります。
TsTodo.tsx を作成しましょう。
src/ts/components/TsTodo.tsx


import React from 'react';
const TsTodo: React.FC = ({
  title,
  checked
}): JSX.Element => (
  <li>
    <label>
      <p>{title}</p>
    </label>
  </li>
);
export default TsTodo;

さて、受け取る型も事前に設計で決めていましたね。
では、それに沿って型定義ファイルも作ってあげましょう。
src/ts/types/Todo.d.ts

export type Todo = {
  title: string;
  checked: boolean;
}

これでTodoの表示用コンポーネントが完成ですね。
続いて、呼び出し側を作成しましょう。
TsTodoList.tsx

TodoにPropsを指定しないとコーディングの時点でエラーが出ていますね。
これは、ビルドも不要なのですぐに実装のミスに気づくことができます。
さあ、ここでもう一つ素敵なメリットが。

なんと、このようにPropsの補完が入ります。
このおかげで、タイプ数も減るし、typoなんて発生しません!
これに慣れると、補完が入らなかったら何か間違ったか?と疑いはじめます。(そして大抵間違ってます。)
そのエラーに沿って修正するときに、Propsが補完として表示されます。
src/ts/pages/TsTodoList.tsx


import React from 'react';
import TsTodo from '../components/TsTodo';
import {Todo} from '../types/Todo';
const TsTodoList: React.FC<{todoList: Todo[]}> = ({
  todoList
}) => (</code></pre>
<ul>{todoList.map((todo: Todo) => ( ))}</ul>
) export default TsTodoList;

これで完成ですね!
最終的な表示はこうなっています。

必要な値が存在していない場合はエディタでエラーが発生するので、実は実装にかかる時間が少ないので、長期的にコードを書くときにはとてもメリットを感じています。
 
 

6. 総評

細かくメリットを書いていたので、最後に今まで書いたメリットをまとめようと思います。
TSのメリット

  1. 1. 型指定による、入力する値の安全性を保つことができる
  2. 2. VisualStudioCodeによる補完機能が最強になる
  3. 3. 詳細に設計をして開発に取り掛かれるので、手戻りが減った
  4. 4. ライブラリを使うときも、使い方を間違えない。
  5. 5. かっこいい

メリットは多いけど、やっぱりNode.jsなどで採用するときなど、環境構築に時間がかかってしまうのも事実です。
なので、僕は
 

・使い捨てのコードはJS
・今後も保守をするコードはTS

 
という形で使い分けていることが多いです。
使い捨てのコードで、tsconfigなどは書きたく無いですからね。
 
以上、僕がTSを使うようになった理由でした。
TSについてはまだまだたくさんのメリットがあるので、皆さんも興味が湧いたらいろんな機能を勉強してみるともっと好きになっていくと思いますよ。
 
AIコンサル/SES/受託開発のご依頼についてはこちら

Fabeee編集部

Fabeee編集部

こちらの記事はFabeee編集部が執筆しております。