TypeScriptを使って嬉しかったこと

新人「先輩、TypeScriptのコーディングできました！」

先輩社員「どれどれ」
先輩社員「いやそこら中コンパイルエラーだらけ...なのは型システムが働いてる証拠だ！」
先輩社員「そうだろ？」

先輩社員「型は...ガードレールだ」
先輩社員「進むべきじゃない場所へ進もうとしたら、ちゃんとブロックしてくれる...」
（ぺこぱ風）

ってことで、**静的型付言語**って良いですよね。
今回は**TypeScript**を使ってみて嬉しかったことを書いてみます。

## 登場人物
ワイ・・・ワイ（36歳）
社長・・・社長
ハスケル子・・・インターンの中学2年生


## 今日から新しいプロジェクト開始
社長「おーい、やめ太郎、ハスケル子ちゃん」
社長「新しいお仕事を獲得してきたで」
社長「**技術記事投稿サイト**を作る案件や」

ワイ「おお〜、さすが社長はんや」

社長「おおきにやで」
社長「ほんで、そのお仕事の話なんやけど」
社長「クライアントはんから一つ要望があんねん」
社長「**React**を使って作ってくれ、って言われてんねや」
社長「やめ太郎、ハスケル子ちゃん、Reactはイケるか？」

ワイ「やった事なくはないですわ」
ハスケル子「私も大丈夫です」

## TypeScriptはどうする？
社長「**TypeScript**はどうしよか？」
社長「そこはクライアントはんからは何も言われてへんねやけど」

ワイ「TSはよう分からんから、今回はやめときまひょ」
ワイ「型とかよう読まれへんし」

ハスケル子「私は絶対TypeScript有りでやりたいです」
ハスケル子「型がないとコード読むの面倒なので...」

## 型がないと面倒、とは
ワイ「いや、型があるほうが**型情報を読まなあかん**から面倒やん」

ハスケル子「いえ、型が書いてあるほうが**コードを把握しやすい**です」

ワイ「ええ...何で...？」

## 例えば：マイページ
ハスケル子「例えば、技術投稿サイトのマイページみたいなのを作るとしますね」

<img width="357" alt="スクリーンショット 2020-01-12 20.44.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295452/573097c7-9191-c264-1ada-6e6f0b27ced1.png">

ハスケル子「↑こんな感じのやつです」

ワイ「ほうほう」

ハスケル子「で、ユーザ情報を表示するための`UserInfo`っていうコンポーネントを作るとします」
ハスケル子「**TypeScriptなし**で書くとすると、コードは↓こんな感じです」

```jsx:/components/UserInfo.jsx
const UserInfo = ({ user }) => (
  <div>
    <section>
      <h2>ユーザ情報</h2>
      <p>アカウント名：{user.account}</p>
      <p>名前：{user.name}</p>
    </section>
    <section>
      <h2>記事一覧</h2>
      <ol>
        {
          user.articles.map(article => (
            <li>
              <a href={article.url}>{article.title}</a>
            </li>
          ))
        }
      </ol>
    </section>
  </div>
)
```

ワイ「なるほどな」

ハスケル子「やめ太郎さんなら、このコンポーネントのコードを見て、」
ハスケル子「**どんな風に使うべきコンポーネント**なのか読み取れますか？」

ワイ「そら簡単やで」
ワイ「**余裕で読み取れますがな**」
ワイ「まず...」

```jsx:/components/UserInfo.jsx
const UserInfo = ({ user }) => (
```

ワイ「↑こう書いてあるから」
ワイ「この`UserInfo`コンポーネントは」
ワイ「親コンポーネントから`user`っていう**props**を受け取ってる...」
ワイ「っちゅうことが分かるわ」

ワイ「他にも...」

```html:/components/UserInfo.jsx
<h2>ユーザ情報</h2>
<p>アカウント名：{user.account}</p>
<p>名前：{user.name}</p>
```

ワイ「↑こんなコードがあるから」
ワイ「親から受け取った`user`っていうpropsは、`account`と`name`というプロパティを持ったオブジェクトである...」
ワイ「ってこともわかるで」

ワイ「あとは...」

```html
<h2>記事一覧</h2>
<ol>
  {
    user.articles.map(article => (
      <li>
        <a href={article.url}>{article.title}</a>
      </li>
    ))
  }
</ol>
```

ワイ「↑こんな部分があるな...」
ワイ「せやから、`user`は`articles`っちゅうプロパティも持っとんな」
ワイ「`map`メソッドを使っているということは、その`user.articles`は配列やということが分かるで」
ワイ「ほんで、その配列の中身はオブジェクトやな」
ワイ「`url`と`title`というプロパティを持ったオブジェクトっちゅうことや」

ハスケル子「はい、そんな感じですよね」
ハスケル子「まとめると、**どんな風に使うべき**コンポーネントだと言えますか？」

ワイ「ええ...？」
ワイ「まあ、まとめるならば」

```js
const user = {
  account: 'Yametaro',
  name: 'やめ太郎',
  articles: [
    {
      title: "記事名1",
      url: "/article1.html"
    },
    {
      title: "記事名2",
      url: "/article2.html"
    }
  ]
};
```

ワイ「propsとして↑こんなオブジェクトを渡して使うべきやな」

ハスケル子「そうですね」

## TypeScriptの場合はどうか

ハスケル子「次に、TypeScriptを使った場合のコードを見てみます」

```tsx:/components/UserInfo.tsx
type Props = {
  user: User
}

type User = {
  account: string,
  name: string,
  articles: Article[]
}

type Article = {
  title: string,
  url: string
}

const UserInfo: React.FC<Props> = ({ user }) => (
  <div>
    <section>
      <h2>ユーザ情報</h2>
      <p>アカウント名：{user.account}</p>
      <p>名前：{user.name}</p>
    </section>
    <section>
      <h2>記事一覧</h2>
      <ol>
        {
          user.articles.map(article => (
            <li>
              <a href={article.url}>{article.title}</a>
            </li>
          ))
        }
      </ol>
    </section>
  </div>
)
```

ハスケル子「↑こんな感じです」

ワイ「ほら、やっぱ型が書いてあるぶん長いやん...」

ハスケル子「そりゃあコード量は少し増えますけど」
ハスケル子「可読性の面でメリットもありますよ」
ハスケル子「例えば...」


```ts:/components/UserInfo.tsx
type Props = {
  user: User
}
```

ハスケル子「↑ここを見ると」
ハスケル子「このコンポーネントは`user`というpropsを受け取る」
ハスケル子「そしてその`user`は**User型**の値である」
ハスケル子「...ということが分かります」

ワイ「なるほどな、受け取るprops一覧がここで分かるわけやな」
ワイ「今回の例では`user`一個だけってことか」
ワイ「でも、なんやの**User型**って」
ワイ「**number型**とか**string型**なら知っとるけど」

ハスケル子「それは↓この部分に書いてあります」

```ts:/components/UserInfo.tsx
type User = {
  account: string,
  name: string,
  articles: Article[]
}
```

ハスケル子「**User型**の値は、`account`という文字列と」
ハスケル子「`name`という文字列...」
ハスケル子「そして`articles`という配列を持っているよ、ってことがわかります」

ワイ「ほうほう、つまり...」
ワイ「**User型**っていうのはハスケル子ちゃんの**自作の型**ってこと？」

ハスケル子「そうです」
ハスケル子「自分で**新しい型**を定義して名前を付けることができるんです」

ワイ「ほー、なんか...」
ワイ「**User**ってのはこんなやつですよ、みたいな」
ワイ「**世界観**的なものが分かりやすいな」

ハスケル子「そうですね」

ワイ「ほんで、`User`が持ってる`account`と`name`が**string型**なのは分かったけど」
ワイ「`Article[]`ってのはどういう型なん？」

ハスケル子「`Article[]`っていうのは」
ハスケル子「**Article型**の値が入ってる**配列**だよ、って意味です」

ワイ「**Article型**ってのは、また自作の型やな？」

ハスケル子「はい」

```ts:/components/UserInfo.tsx
type Article = {
  title: string,
  url: string
}
```

ハスケル子「↑この部分で**Article型**を定義しています」

ワイ「なるほど」
ワイ「**Article型**の値は、`title`と`url`というプロパティを持ってますよ...」
ワイ「ほんで、`title`も`url`も文字列ですよ...」
ワイ「っちゅうことやな」

ハスケル子「そうです」

## 型が書いてあると、何が嬉しいか
ハスケル子「TypeScriptなしの場合は」
ハスケル子「コンポーネントの中身を**全部**読んで...」

> 「なるほど、このコンポーネントには`user`というオブジェクトを渡して使うんだな」
> 「その`user`は、`account`と`name`と`articles`というプロパティを持ってるんだな」
> 「`articles`は`map`メソッドを持っているようだから、配列だな・・・！」

ハスケル子「...っていうことが**ようやく**分かったじゃないですか」

ワイ「せやな」

ハスケル子「でもTypeScriptありの場合だと」

```ts:/components/UserInfo.tsx
type Props = {
  user: User
}

type User = {
  account: string,
  name: string,
  articles: Article[]
}

type Article = {
  title: string,
  url: string
}
```

ハスケル子「↑この型定義の部分を見ただけで...」

```js
const user = {
  account: 'Yametaro',
  name: 'やめ太郎',
  articles: [
    {
      title: "記事名1",
      url: "/article1.html"
    },
    {
      title: "記事名2",
      url: "/article2.html"
    }
  ]
};
```

ハスケル子「↑こんなpropsを受け取るコンポーネントだな！」
ハスケル子「ってことが分かるじゃないですか」
ハスケル子「コンポーネントの実装部分を読まなくても！」

ワイ「おお...」
ワイ「やっぱリーダブルやなぁ...」

社長「（何が**やっぱ**やねん...）」

ワイ「仕事やと、一つの案件のコーディングを複数人で担当することも多いから」
ワイ「人の作ったコンポーネントを使う機会とかも多いしな」
ワイ「せやから、読み取りやすいのはええよなぁ」

ワイ「あと思ったんやけど」
ワイ「型ってなんか、コメントみたいな効果もあるんやね」
ワイ「このプロパティには文字列を入れてくださいな、みたいな」
ワイ「コード内に仕様書が書いてある感じがええな」

ハスケル子「そうですよね」
ハスケル子「しかも、ちゃんと守らなきゃ前に進めない...」
ハスケル子「**強制力を持ったコメント**ですよね」
ハスケル子「型定義の通りにpropsを渡さないとエラーが出て、コンパイルが通らない...」
ハスケル子「だから、マウスでぽちぽちページを見て回る前に**ミスに気付ける**んです」

ワイ「ああ、普通はコードを実行してみるまで」
ワイ「エラーが出るかどうか分からへんもんなぁ...」
ワイ「それはええかも...」

## 他にも嬉しいことが
ハスケル子「そういえば、やめ太郎さんって」
ハスケル子「`name`っていう単語をよく`namae`って**スペルミス**するじゃないですか」

ワイ「まぁ、比較的するな」

ハスケル子「そういう**タイポ対策**にもTypeScriptが役立ったりしますよ」
ハスケル子「例えば...」

```html:/components/UserInfo.tsx
<p>名前：{user.namae}</p>
```

ハスケル子「↑こんな風にタイポしちゃったとしたら...」

> Property 'namae' does not exist on type 'User'. Did you mean 'name'?
> （プロパティ「namae」はタイプ「User」に存在しません。 「name」という意味ですか？

ハスケル子「なんて教えてくれるんです」

ワイ「おお、まじか...」
ワイ「まさにワイのための機能やん...」

ハスケル子「そもそもタイポしなくなるようなメリットもありますよ」

<img width="562" alt="スクリーンショット 2020-01-12 22.14.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295452/0bc1c526-4e91-1d2a-92f9-ba8cc2b6b466.png">

ハスケル子「↑こんな風に、`user.`まで打つと入力候補が出てくるので」
ハスケル子「その中から選択すればいいんです」

ワイ「おお...」
ワイ「もう、使わん理由ないやん...」

**ワイ「ハスケル子先生...！！」**
**ワイ「TypeScriptがしたいです......」**

社長「ほな、決まりやな！」

## そんなこんなで終業時刻

ワイ「ハスケル子ちゃん、今日も色々教えてくれてありがとうやで...」

ハスケル子「教えるの楽しいから全然いいですよ」

ワイ「ハスケル子ちゃんは凄いなぁ...まだ中学生なのに色々知ってて...」
ワイ「チート過ぎるハスケル子ちゃんを見てると、自分が情けなくなってくるわ...」
ワイ「負け過ぎてるんやもん...」

ハスケル子「私もよく思いますよ」
ハスケル子「私だけ周りの子たちより出遅れてて不安になったり、嫉妬したりします」
ハスケル子「でも結局」
ハスケル子「今の自分から生きることしかできないんです」
ハスケル子「誰かに負けてても、誰かより劣っていても」
ハスケル子「自分なりの精一杯をやればいいんです」

ワイ「ハスケル子ちゃん...！」

ハスケル子「...もしくは、嫌なら死ぬとか...」

ワイ「**いや死を提案すな！**」

**〜おしまい〜**

## 続編もよろしくやで
[**4歳娘「パパ、実行時エラーの出ないフロントエンド言語ってなーんだ？」**](https://qiita.com/Yametaro/items/5a8474523d7ba3a3a3e4)
## さらに続編
[**テストしやすい「純粋」な関数とは？**](https://qiita.com/Yametaro/items/3ec5a7d89afa1a0e9f15)


## おまけ：簡単にReact + TypeScriptを始めるには
React + TypeScriptを触ってみたい人は、

`npx create-next-app --example with-typescript my-app-name`
`cd my-app-name`
`npm run dev`

↑この3つのコマンドを打ってから
`http://localhost:3000/`にアクセスするだけやで！
（もちろんNode.jsは先にインストールしといてや！）