きみはねこみたいなにゃんにゃんなまほう

ねこもスクリプトをかくなり

react-redux-typescript-guide を読んだ感触

Redux + TypeScript の検証作業で疲弊していたところで react-redux-typescript-guide を読んだら思ったより色々まとまっていて、検証のモチベーションがちょっと高まりました、という感想文です。

現在 Redux + TypeScript でアプリを作ろうと色々調べています。 業務でも趣味でも Redux を使った経験はほとんどありません。 認証情報を格納するためのストアとしてシンプルな reducer と数個の action を定義した程度です。

前回のエントリでは typescript-fsatypesafe-actions についてごく簡単に触った感触について書きました。

dispatch に連動して副作用を実現する redux-observableredux-thunk については何度か手元の試作プロジェクトで軽く触った程度です。 軽く触った程度ですが Redux + Typescript の荒波には十分揉まれました。 分かりやすい進捗が出せなくてそろそろ辛いです。

そして react-redux-typescript-guide というガイドを見つけました。

自分でライブラリを探している途中で何度かページ自体は目にしていたのですが、改めて読んでみたところかなり内容がまとまっているようでした。ここまで荒波にまみれてなんとなく掴めてきた理解を整理する上でも、一旦頭を空にして読む価値のありそうなガイドです。写経や読経は世俗の煩悩にまみれた状態でこそ効力を示します。

このガイドでメインで使われているのは typesafe-actionsredux-observable の組み合わせです。

今回は react-redux-typescript-guide の概要をまとめ...るようなことはせず、どの部分を読んでどういう理解になったか、何が得られたかの、ただの感想文を残していこうと思います。

コード類はほとんど引用していないので読みづらいですが済みません。

Type Definitions & Complementary Libraries

まずは補助的に使うライブラリの紹介です。 typesafe-actions はむしろメインで使うライブラリですね。

React Type Cheatsheet

React + TypeScript のベースとなる型情報です。この辺はある程度 React + TypeScript の経験があれば大体把握しているはずですが、それでも新しく気づいたことがあったので、網羅性というものの価値を感じます。

  • React.CSSPRoperties
    • Material-UI でたまに JSS 用に型定義が欲しくなることがありますが React に含まれていたのは初めて知りました

Component Type Pattern

チートシートの続きで、頻出パターンの逆引き一覧になっています。ここも発見が多いです。実装の段階でお世話になりそうです。

Stateful Components

  • Stateful Components って constructor 無しでもいける
  • defaultProps の例はちょっとわかりづらい(というより読みづらい)

Render Props

Apollo なんかで <Query>{({ loading }) => ... }</Query> とかやるやつですね。 そういえば Render Props と HOC の良し悪しってあまり把握してないんですよね...

Higher-Order Components

そして Higher-Order Components の書き方です。色々理解していないことだらけでした。

  • typeclass の中で定義できる
  • Enhanced なコンポーネントに名前をちゃんとつけててえらい
  • そういえば recompose はこのガイドの中では触れられていないのが気になりました
  • Error Boundary の例もあるのは嬉しいです

以前、FlowApollo を利用していたことがあるので、そこまで苦労しないで読めました。

bindActionCreators

Redux とのつなぎの部分で利用する bindActionCreators (初めて知りました)でワンポイントです。

Redux の bindActionCreators を使うときは props 内で () => void を使うとコンパイルエラーになるけれど () => any で代用可能、という注意書きがあり、このガイドの例もそれで実装されているみたいです。

Redux

そして来ました Redux です。 typesafe-actions を使って action を定義していきますが、 詳しくは The Mighty Tutorial を読んでね、と書いてありますね。

そして 前回 気になったところですが、リンク先にも書いてあります。 大事そうなのでここだけ原文で引用します。

WARNING: When using string constants for action type, please be sure to use simple string literals. Don't use string concatenation, template strings or object map because your type will lose the type information, widening to it's supertype string (this is how TypeScript works).

String Literal を型推論に利用しているので template strings や object map を使うと型が string に落ちてしまい action type の型情報が得られなくなる(= ペイロードの型付けが行えなくなる)ということです。 大変そうですが地道に全ての action の名前をつけていくしかなさそうです。

型付けに別の手法を取っている typescript-fsa にはこういう制約はなさそうです。ここで規模のあるアプリを作成した時に、最終的な使い勝手がどう変わるかが、今後の検証でも気になるところです。

Reducers

State の定義には readonly を使うといいよという話。 ReadonlyArrayutility-typesDeepReadonly も便利そうです。

他は TypeScript のスマートな型解析で if ステートメント内の型がその条件により type narrowing されるという話ですね。

Store Configuration

特に目立ったところはなく、以下の微妙な違いに気をつけてさえすればいいと思います。

  • RootAction は全ての Action の Union 型
  • RootStatecombineReducer された(構造化された) State を示す型

いちいち Root とつけるかは好みですが、実際、プロジェクトを構造化した状態で import を大量に行なっていたりすると、実際は何を参照しているのかあやふやになってくるので、特別な名前で参照できると安心感があります。

他に書かれているのは redux-observable の epic を middleware に仕込むところくらいです。

Async Flow

これは The Mighty Tutorial へのリンクで済まされています。これについてはまたそのうち別途書くかもしれません。

Selectors

これは完全に初見の概念だったのですが、Selector とは Store 上のあるデータに別のデータを適用した結果をキャッシュしておき、その結果が依存する State の変更があるまでそれを保持し続けることを行うライブラリの総称のようです。Computing Derived Data - Redux にも項目があります。

Vue.js の computed に近いといえば近いのでしょうか(あれはテンプレート中で参照するためのものなので用途が違うかもしれませんが)。

Tools & Recipes

個人的に一番嬉しかったところかもしれません。よく利用されるツールの設定例が紹介されています。

  • Common Npm Scripts
  • tsconfig.json
    • @src/... でプロジェクトルート下の ./src を参照するやり方があるのを初めて知りました
      • でもどうやらデフォルトで import src/... が動作するみたいですね...
      • この辺はまた検証してみたいです
    • lib で 何を指定したらいいかの答えはここにありました(毎回迷うんですよね...)
  • Vendor Types Augmentation
    • ライブラリの型定義がおかしい場合に quick fix してやり過ごす方法も載っています

感想

...と、一通り読んできましたが、ただ単に読んだだけで特に手を動かして検証を行なったわけではないので、何ができるようになったではありません。それでも多くの試したいことが発見できたので、技術検証のモチベーションを高める効果はあったと思います。もしくは単に鮮度のいいネタを提供してもらえたと言うべきでしょうか。

とりあえず Redux + TypeScript にかき乱された頭の中は整流されたような気がします。 これでまた型システムの闇に立ち向かえそうな気がします。

気になったところ

ガイドを読んでいて、後で調べたいと思ったところです。

  • HOC と Render Props の比較
    • 両者とも同様にDI的なことを行なっているので、手法の差がどう評価されているのか気になります
  • TypeScript の import path の設定
    • よく ../../../api のように ./src 直下近くに置いたライブラリが参照しづらくなる問題が TypeScript では tsconfig.jsonbaseUrl で解決されているみたいですが、その動作について精査してみたいです
    • import @src/... のパターンと import src/... のパターンがあるみたいですが、どちらが推奨されているのかも気になります