title: Best practice redux actions with flowtype?
body: <p>I want to write redux with flowtype, but I have questions about how to do that.</p>
  
  <h2>Redux with Flowtype</h2>
  
  <pre class="lang-js prettyprint-override"><code>type ActionType =
    | 'A'
    | 'B'
    ;
  
  // A generic type conforming to Flux Standard Action
  type ActionT&lt;A, P&gt; = {|
    type: A,
    payload?: P | Error,
    error?: boolean,
    meta?: mixed
  |};
  
  type Action =
    | ActionT&lt;'A', string&gt;
    | ActionT&lt;'B', number&gt;
    ;
  
  const error: Error = new Error('wrong');
  const info = { href: '...' };
  
  // ---- valid actions with flowtype ----
  const action1: Action = {type: 'A', payload: 'hello' };
  const action2: Action = {type: 'A', payload: error, error: true };  // The 'payload' could be an error.
  const action3: Action = {type: 'A', payload: 'hello', meta: info };  // We can have 'meta'.
  
  // ---- invalid actions with flowtype ----
  const actionNG1: Action = {type: 'C', payload: 'hello' };  // Wrong 'type' value. The type 'C' is not allowed.
  const actionNG2: Action = {type: 'B', payload: 'hello' };  // Wrong value type of 'payload'. It should be a number.
  const actionNG3: Action = {type: 'A', payload: 'hello', threshold: 3 };  // Extra property 'threshold' is not allowed. It should conform to type ActionT.
  </code></pre>
  
  <ul>
  <li>I use <code>ActionType</code> instead of constants to check the valid <code>type</code> values. </li>
  <li>The type <code>ActionT</code> conforms <a href="https://github.com/acdlite/flux-standard-action" rel="nofollow noreferrer">Flux Standard Action</a> to ensure the structure of Redux actions.</li>
  <li>The type <code>Action</code> declares the concrete types for all actions that we'll use in our App.</li>
  </ul>
  
  <h3>Question 1: how to ensure the first type passed to <code>ActionT</code> would be the type of <code>ActionType</code> (or at least, should be a <code>string</code> type)?</h3>
  
  <p>For example, adding a new type <code>'C'</code> in not allowed, because <code>ActionType</code> only accepts <code>'A'</code> and <code>'B'</code>.</p>
  
  <pre class="lang-js prettyprint-override"><code>type ActionType =
    | 'A'
    | 'B'
    ;
  
  type Action =
    | ActionT&lt;'A', string&gt;
    | ActionT&lt;'B', number&gt;
    | ActionT&lt;'C', number&gt;  // Should Raise an error
    ;
  </code></pre>
  
  <p>Does it make sense?</p>
  
  <h3>Question 2: how to write the reducers (and <code>thunk</code>) with flowtype and Immutable.js?</h3>
  
  <p>I've written a buildReducer to bind to a initial state.</p>
  
  <pre class="lang-js prettyprint-override"><code>type Action =
    | ActionT&lt;'SELECT_COUNTRY', string&gt;
    ;
  
  const buildReducer = (initialState, reducerMap) =&gt;
    (state = initialState, action) =&gt; {
      const reducer = reducerMap[action.type];
      return (reducer) ? reducer(state, action) : state;
    };
  
  const initialState = Immutable.fromJS({
    selectedCountry: 'US'
  })
  
  const reducers = {
    ['SELECT_COUNTRY']: (state, action) =&gt; {
      // how to know the type of payload is string type?
      // how to ensure that `state.set(...)` gets right type of the value for the key?
      return state.set('selectedCountry', action.payload)
    }
  }
  
  const appReducer = buildReducer(initialState, reducers)
  </code></pre>
  
  <p>How can I check the <code>payload</code> type in the <code>reducers</code> for action type <code>SELECT_COUNTRY</code> with flowtype ?</p>
  
  <p>How can I apply the payload value to the <code>immutable</code> state with flowtype check?</p>