typescript-fsaしゅごい
なんでしゅごいのかは@m0aさんのこちらの記事が分かりやすいです。
FSAって何って方はこちら。
この記事はtypescript-fsaによって作られるactionについて説明します。
Actionを作る
actionを作るにはまずactionCreator
を作ります
import actionCreatorFactory from 'typescript-fsa'
const actionCreator = actionCreatorFacory()
ここからactionを定義していきます
// typeが'HogeAction'かつpayloadの型がstringなFSA
const hogeAction = actionCreator<string>('hogeAction')
hogeAction.type
// 'hogeAction'
hogeAction('a')
// { type: 'hogeAction', payload: 'a' }
// payloadには型チェックが入る
hogeAction(1)
// error TS2345: Argument of type '1' is not assignable to parameter of type 'string'.
// payload無し
const hugaAction = actionCreator<void>('hugaAction')
const piyoAction = actionCreator('piyoAction')
// error
const errorAction = actionCreator<Error>('errorAction')
errorAction(new Error('hoge'))
// {
// type: 'errorAction',
// payload: Error: hoge
// at /home/kc5m/src/localhost/kc5m/fsa-saga-sample/[eval].ts:1:13
// // 省略
// error: true // Error型を渡すと自動的に{error: true}が付与される(条件変更可)
// }
非同期用Actionを作る
typescript-fsa
には非同期処理向けに非同期用Actionをいい感じに作ってくれるAPIも用意されています。
AsyncActionCreator
(AAC)と呼称されています。
実際にAACを定義してみます。
// AAC定義
const hogeAsyncAction = actionCreator.async<string, number, Error>('hogeAsyncAction')
actionCreator.async()
はParams
, Result
, Error
(javascriptのError
型とは別)の3つの型からstarted
, done
, failed
の3つのAction(FSA)を生成します。
上記の例で言うとstring
がParams
, number
がResult
, Error
がError
に相当します。
生成された3つのActionは非同期処理での利用を想定されています。例えば以下の非同期関数があったとします。
const f = async (params: string): Promise<number> {
const result = await someAsyncFunc(pars)
if (!result) {
throw new Error('error')
}
return 0
}
started
はf()
が実行されたタイミングを、done
はreturn
されたタイミングを、そしてfailed
はthrow
されたタイミングをそれぞれ表現していると考えると分かりやすいかも知れません。
さて、このAACですが通常のActionではないのでそのままActionとして使えません。
hogeAsyncAction('aaa')
// error TS2349: This expression is not callable.
そのためAAC内propertyに生成されたActionを使う必要があります。
// started
hogeAsyncAction.started('a')
// { type: 'hogeAsyncAction_STARTED', payload: 'a' }
started
と同じようにdone
とfailed
を使うとerrorが出ます。
// done
hogeAsyhogeAsyncAction.done(2)
// error TS2345: Argument of type '2' is not assignable to parameter of type '{ params: string; } & { result: number; }'.
// failed
hogeAsyhogeAsyncAction.failed(new Error('hoge'))
// error TS2345: Argument of type 'Error' is not assignable to parameter of type '{ params: string; } & { error: Error; }'.
AACが作るdone
, failed
のpayloadの型は拡張されていて、payloadの中にstarted
に渡したpayloadが含まれるようになっています。
上記の例で言うとerrorにも書かれていますがdone
は{ params: string } & { result: number }
型に、failed
は{ params: string } & { error: Error }
型になります。
hogeAsyncAction.done({ params: 'a', result: 1 })
// { type: 'hogeAsyncAction_DONE', payload: { params: 'a', result: 1 }}
hogeAsyncAction.failed({ params: 'a', error: new Error('aaa') })
// {
// type: 'hogeAsyncAction_FAILED',
// payload: {
// error: Error: aaa
// at /home/kc5m/src/localhost/kc5m/fsa-saga-sample/[eval].ts:1:33
// // 省略
// params: 'a'
// },
// error: true
// }
まとめると以下のようなります。
actionCreator.async<Params, Result, Error>()
で作られるactionのpayloadの型は
-
started
:Params
-
done
:{ params: Params } & { result: Result }
-
failed
:{ params: Params } & { error: Error }
また、done
はResult
にError
型(new Error()
とか)が来てもerror: true
になりません。FAILED
はError
にError
型以外が来てもerror: true
になります。
const fugaAsyncAction = actionCreator.async<string, Error, string>('fugaAsyncAction')
fugaAsyncAction.done({result: new Error('aaa'), params: 'a'})
// {
// type: 'fugaAsyncAction_DONE',
// payload: {
// result: Error: aaa
// at /home/kc5m/src/localhost/kc5m/fsa-saga-sample/[eval].ts:1:32
// // 省略
// params: 'a'
// }
// }
fugaAsyncAction.failed({error: 'a', params: 'a'})
// {
// type: 'fugaAsyncAction_FAILED',
// payload: { error: 'a', params: 'a' },
// error: true
// }
最後に
typescript-fsa
を使うことによって、型チェックが走るFSAの定義及び非同期処理用に複数のFSAを少ない行数で定義できます。
これ単体だけでも便利ですが、同じ作者より提供されている以下のCompanion Packagesを併用することにより更に便利に使うことができます(リンク省略)。
-
typescript-fsa-redux-saga
typescript-fsa-redux-observable
typescript-fsa-redux-thunk
typescript-fsa-reducers
以上