title: Understanding Typescript Record type with React's useContext
body: <p>I'm having some issues understanding the record type in a generator function I'm developing for React contexts.</p>
  <p>Here's my generator function:</p>
  <pre><code>import * as React from 'react'
  
  export type State = Record&lt;string, unknown&gt;
  export type Action = { type: string; payload?: unknown }
  
  // eslint-disable-next-line @typescript-eslint/ban-types
  export type Actions = Record&lt;string, Function&gt;
  
  
  export type AppContext = { state: State; actions: Actions }
  export type Reducer = (state: State, action: Action) =&gt; State
  
  type ProviderProps = Record&lt;string, unknown&gt;
  type FullContext = {
      Context: React.Context&lt;AppContext&gt;
      Provider: React.FC&lt;ProviderProps&gt;
  }
  
  /**
   * Automates context creation
   *
   * @param {Reducer} reducer
   * @param {Actions} actions
   * @param {State} initialState
   * @returns {Contex, Provider}
   */
  export default (
      reducer: Reducer,
      actions: Actions,
      initialState: State,
      init: () =&gt; State = (): State =&gt; initialState,
  ): FullContext =&gt; {
      const Context = React.createContext&lt;AppContext&gt;({
          state: { ...initialState },
          actions,
      })
  
      const Provider = ({ children }: { children?: React.ReactNode }) =&gt; {
          const [state, dispatch] = React.useReducer(reducer, initialState, init)
  
          const boundActions: Actions = {}
          for (const key in actions) {
              boundActions[key] = actions[key](dispatch)
          }
  
          return (
              &lt;Context.Provider value={{ state, actions: { ...boundActions } }}&gt;
                  {children}
              &lt;/Context.Provider&gt;
          )
      }
  
      return {
          Context,
          Provider,
      }
  }
  
  </code></pre>
  <p>The core of the issue is here:</p>
  <pre><code>        const boundActions: Actions = {}
          for (const key in actions) {
              boundActions[key] = actions[key](dispatch)
          }
  </code></pre>
  <p>What I'm trying to do is to have a function I can call with a reducer and inital state to generate a Context provider that I can use anywhere in the app. In this case, I'm attempting to generate an <code>AuthContext</code>. This context will take a reducer that looks like this:</p>
  <pre><code>const authReducer: Reducer = (state: State, action: Action): State =&gt; {
      switch (action.type) {
          case 'login':
              return { ...state, isLogged: true, avoidLogin: false }
          case 'logout':
              return { ...state, isLogged: false, avoidLogin: true }
          default:
              return { ...state }
      }
  }
  </code></pre>
  <p>Quite barebones, but it basically changes some booleans in an object.</p>
  <p>Now, this code actually works but what bugs me is the use of the Function type in the declaration of the Actions type.</p>
  <p><code>export type Actions = Record&lt;string, Function&gt;</code></p>
  <p>using <code>unknown</code> also works, but now typescript complains that <code>Object is of type 'unknown'.</code> when doing: <code>boundActions[key] = actions[key](dispatch)</code>, specifically on <code>actions[key]</code>, because I'm calling it as a function.</p>
  <p>Actions are functions that take in a function (dispatch) as an argument and return a <code>State</code> object.</p>
  <p>Here's my actions declaration to further illustrate:</p>
  <pre><code>const actions: Actions = {
      login: (dispatch: (action: Action) =&gt; void) =&gt; () =&gt; {
          dispatch({ type: 'login' })
      },
      logout: (dispatch: (action: Action) =&gt; void) =&gt; () =&gt; {
          dispatch({ type: 'logout' })
      },
  }
  </code></pre>
  <p>If I console log <code>boundActions</code> in my generator I get something like:</p>
  <pre><code>Object {
    &quot;login&quot;: [Function anonymous],
    &quot;logout&quot;: [Function anonymous],
  }
  </code></pre>
  <p>This is precisely what I want as I want to be able to call these functions anywhere in my code and this will, in turn, call the dispatch function of a specific reducer changing the state of a specific context.</p>
  <p>Now, I'm fairly new with Typescript, but my gut tells me the declaration of the <code>Actions</code> type should be something like:</p>
  <p><code>export type Actions = Record&lt;string, (dispatch:Function) =&gt; State&gt;</code></p>
  <p>The problem with this is:
  1- it doesn't work because now <code>boundActions</code> say something like:</p>
  <pre><code>Type 'Record&lt;string, unknown&gt;' is not assignable to type '(dispatch: Function) =&gt; Record&lt;string, unknown&gt;'.
    Type 'Record&lt;string, unknown&gt;' provides no match for the signature '(dispatch: Function): Record&lt;string, unknown&gt;'.
  </code></pre>
  <p>2- I'm still using the Function type which isn't typesafe.</p>
  <p>Now, <code>dispatch</code> takes a an action as parameter <code>export type Action = { type: string; payload?: unknown }</code></p>
  <p>So my guess would be <code>export type Actions = Record&lt;string, (dispatch(arg:Action)) =&gt; State&gt;</code></p>
  <p>but this doesn't work either because it's not valid typescript code.</p>
  <p>I know this case is kind of unnecessarily complicated, but I just want to better understand the use of Record in this specific case, where a record has <code>string</code> keys and <code>Function</code> values.</p>
  <p>At the end of the day, all I want is to do something like:</p>
  <pre><code>export default function Login(): JSX.Element {
      const {
          actions: { login },
      } = React.useContext(AuthContext)
  
      return (
          &lt;View&gt;
              &lt;Button text='Entrar' onPress={() =&gt; login()} /&gt;
          &lt;/View&gt;
      )
  }
  </code></pre>
  <p>Which actually works, but it is not typesafe.</p>
  <p>Thank you.</p>