TypeScript
redux
ngrx

ts-actionを使ってRedux (@ngrx) のActionを簡潔に記述する

More than 1 year has passed since last update.

Reduxでの開発では、しばしばAction定義の肥大化に悩まされます。

冗長な記述をなくすライブラリが色々あるようですが、TypeScriptベースのts-actionがとても良さそうだったので、「Angular + @ngrx」での使い心地を見てみました。

通常のコード

// Action
enum BookActionTypes {
  SEARCH = "[Books] Search",
  SEARCH_COMPLETE = "[Books] Search Complete",
  SEARCH_ERROR = "[Books] Search Error"
}

class Search implements Action {
  readonly type = BookActionTypes.SEARCH;
  constructor(public payload: string) {}
}

class SearchComplete implements Action {
  readonly type = BookActionTypes.SEARCH_COMPLETE;
  constructor(public payload: Book[]) {}
}

class SearchError implements Action {
  readonly type = BookActionTypes.SEARCH_ERROR;
  constructor(public payload: string) {}
}

type All = Search | SearchComplete | SearchError;

// Dispatch
store.dispatch(new Search("hello"));

// Reducer
function reducer(state: State = initialState, action: All): State {
  switch (action.type) {
  case BookActionTypes.SEARCH:
    return { ...state, query: action.payload };
  case BookActionTypes.SEARCH_COMPLETE:
    return { ...state, books: action.payload };
  case BookActionTypes.SEARCH_ERROR:
    return { ...state, error: action.payload };
  default:
    return state;
  }
}

ts-actionを使用したコード

// Action
const Search = action("[Books] Search", payload<string>());
const SearchComplete = action("[Books] Search Complete", payload<Book[]>());
const SearchError = action("[Books] Search Error", payload<string>());
const All = union(Search, SearchComplete, SearchError);

// Dispatch
store.dispatch(new Search("hello"));

// Reducer
function reducer(state: State = initialState, action: typeof All): State {
  switch (action.type) {
  case Search.type:
    return { ...state, query: action.payload };
  case SearchComplete.type:
    return { ...state, books: action.payload };
  case SearchError.type:
    return { ...state, error: action.payload };
  default:
    return state;
  }
}

なかなか良さそうです。

P.S. @ngrx本家にFeature requestを送ったようですが、残念ながら良い返答は得られなかったようです。(https://github.com/ngrx/platform/issues/584)