はじめに
Typescript+ReactNative+Reduxを勉強中なのですが、
下記のような記述が個人的にはすごく気持ち悪い。
HogeAction.ts
export const HOGE_ACTION_1: string = 'HOGE_ACTION_1';
export const HOGE_ACTION_2: string = 'HOGE_ACTION_2';
export class HogeAction1 {
type : string = HOGE_ACTION_1;
data1: string = '';
}
export class HogeAction2 {
type : string = HOGE_ACTION_2;
data2: boolean = false;
data3: number = 0;
}
Reducer側ではtypeを参照してどのActionか判定しているけど、Actionはちゃんと型として定義しているのだからそんなことする必要はないのでは??
と思ったらReducerではActionをanyで受けているのか...
HogeReducer.ts
import {
HOGE_ACTION_1,
HOGE_ACTION_2,
HogeAction1,
HogeAction2
} from '../HogeAction';
import HogeState from '../HogeState';
// Stateを初期化
const initialState: HogeState = new HogeState();
export default function HogeReducer(state = initialState, action : any){
if(!action){
return state;
}
switch(action.type){
case HOGE_ACTION_1:
// HogeAction1処理...
case HOGE_ACTION_2:
// HogeAction2処理...
default:
return state;
}
}
修正後
それならActionBaseというActionの基底クラスを作って、そこで各Actionのインスタンスの区別がつくようにしてあげればいいのでは(言語化すると何言ってるのか分からんので、下記コードを見てください)
ActionBase.ts
export default class ActionBase {
// コンストラクタ
constructor(){
}
// クラス名
public type : string = this.getClassName();
public getClassName() {
if(!this || !this.constructor){
return '';
}
// コンストラクタからクラス名を取得
const constructorRegex: RegExp =/function (.{1,})\(/;
const results = (constructorRegex).exec((<any> this).constructor.toString());
return (results && results.length > 1) ? results[1] : '';
}
}
getClassName()でインスタンス化した各Actionのコンストラクタ文字列を呼び出してActionを特定している。
typeはActionBaseに持たせておけばよいので、各Actionクラスは純粋に操作するプロパティだけを持たせる。
HogeAction.ts
import ActionBase from './ActionBase';
//export const HOGE_ACTION_1: string = 'HOGE_ACTION_1';
//export const HOGE_ACTION_2: string = 'HOGE_ACTION_2';
export class HogeAction1 extends ActionBase{
//type : string = HOGE_ACTION_1;
data1: string = '';
}
export class HogeAction2 extends ActionBase{
//type : string = HOGE_ACTION_2;
data2: boolean = false;
data3: number = 0;
}
Reducerはaction.typeと各Actionクラスの.nameを突合させて判定している。
HogeReducer.ts
import {
HogeAction1,
HogeAction2
} from '../HogeAction';
import HogeState from '../HogeState';
import ActionBase from '../ActionBase';
// Stateを初期化
const initialState: HogeState = new HogeState();
export default function HogeReducer(state = initialState, action : ActionBase){
if(!action){
return state;
}
switch(action.type){
case HogeAction1.name:
// HogeAction1処理...
case HogeAction2.name:
// HogeAction2処理...
default:
return state;
}
}
これで少しはモヤっとする書き方をせずに済むかも。
もっと良い書き方があれば教えていただければ幸いです。