Redux(https://redux.js.org/) > Basics > Example:Todo List をtypescriptで動かす

reduxのチュートリアルをtypescriptで書こうとしたのだけれど、すんなり動かなかったので備忘も兼ねて動かせるようになるまでの経緯をまとめます。
今回色々ハマったのですが、せっかくのtypescriptの勉強なのでこの記事で作ったコードはany無しでやりました。


#Reduxに触れる
以下のものをTSで書き直しています。
元サイト：https://redux.js.org/basics/example-todo-list

完成したのは以下。create-react-appを使いました。
https://github.com/HiroshiAkutsu/TodoList

参考：https://github.com/Microsoft/TypeScript-React-Starter

昨日初めてreduxに触れて、それを勉強したてのtypescriptで書こうとしたのだから、すんなり行かないのは当たり前です。
それにしてもredux、最初は全然頭に入ってこなくて朝から勉強しだしても一日中モヤモヤしてたけど、深夜の2時くらいに眠りにつくタイミングで、自分の何がいけなかったのかようやく閃きました。

エラーしてて昨晩どうしても解決できなかったのは２箇所。

# dispatchの型

- [元サイト：containers/AddTodo.js](https://redux.js.org/basics/example-todo-list#containersaddtodo.js)の5行目
`{dispatch}`の型を何にしていいのかわかりませんでした。

一晩悩んでたどり着いた答えは
`{dispatch}: {dispatch: Dispatch<{type:string, text: string}>}`
でした。
これでコンパイル通りました。
そもそも初歩的な分割代入の概念がよくわかっていませんでした。
[分割代入](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
[アロー関数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)
これ読んで理解しました。
## 分割代入の復習

```javascript
var materials = [
  "Hydrogen",
  "Helium",
  "Lithium",
  "Beryl­lium"
].map({length} => length) //-> [8, 6, 7, 9]

```
この場合,mapの第一引数に渡される配列の要素(Stringオブジェクト)のlengthプロパティの値をlengthという変数に直接代入しているということになります。

```javascript
const {メソッド名} = オブジェクト;
```
と書くと、メソッド名を変数名としてオブジェクトがもともと持っていたメソッドないしプロパティが、変数名の呼び出しだけで利用できます。

```javascript
const {length} = "abcdef";
console.log(length); //-> 6
```

と書くと、length変数に"abcdef"というStringオブジェクトのlengthプロパティの値が入ります。
`const {length} = "Hydrogen";`
と
`const {length: length} = "Hydrogen";`
は同義で、
`const {length: length} = "Hydrogen";`
は
`const length = "Hydrogen".length;`
と同義なんですね。
つまり3段論法で
`const {length} = "Hydrogen";`
は
`const length = "Hydrogen".length;`
と同義ということ。

そして、元のコードに戻って、仮引数に`({dispatch})`と渡されたらそれは({dispatch: dispatch})と同義で、dispatchのkeyに対して、Dispatchという型のdispatchメソッドが渡されているということだから、シグネチャは`{dispatch: Dispatch<{...}>}`となります。。。

何言ってるかわかんねえ笑。
昨日悩みに悩んで全然寝れなかったので雑ですみません。次いきます。

# OwnPropsの渡し方
もう一つどうしてもコンパイルエラーになってしまったのが、[components/Footer.js 9,13,17行目](
https://www.codementor.io/mz026/getting-started-with-react-redux-an-intro-8r6kurcxf)のfilterプロパティの渡す箇所。
以下エラーが吐き出されました。

```
[ts]
型 '{ children: string; filter: string; }' を型 'IntrinsicAttributes & IntrinsicClassAttributes<Component<Pick<LinkProps, "children"> & OwnProps, ...' に割り当てることはできません。
  型 '{ children: string; filter: string; }' を型 'Readonly<Pick<LinkProps, "children"> & OwnProps>' に割り当てることはできません。
    プロパティ 'children' の型に互換性がありません。
      型 'string' を型 'Node' に割り当てることはできません。
```

これは以下のissueにヒント（というか答え）がありました。
https://github.com/piotrwitek/react-redux-typescript-guide/issues/1
コンテナの[FilterLink](https://redux.js.org/basics/example-todo-list#containersfilterlink.js)でエクスポートしているFilterLinkコンポーネントの型をReact.ComponentClass<OwnProps>にキャストすればいいだけでした。

```typescript:containers/FilterLink.tsx

interface OwnProps {
    filter: string; // childrenのプロパティはなくてもコンパイル通りました。。。
}

// ...

export default FilterLink as React.ComponentClass<OwnProps>;
```

これでtslint上もコンパイルが通ります。

# まとめ
- reduxの仕組みをきちんと理解しないままtypescriptでredux本家サイトのExampleを書き出すとゴールが余計に遠く感じられます
- Dispatchの型の扱いに注意（ここでは扱わなかったが、ジェネリックの指定もあり、ややこしい）
- 親からコンテナに渡されたPropsの扱いはコンテナのexport文で`React.ComponentClass<OwnProps>`にキャストする