piotrwitek / typesafe-actions

Typesafe utilities for "action-creators" in Redux / Flux Architecture
https://codesandbox.io/s/github/piotrwitek/typesafe-actions/tree/master/codesandbox
MIT License
2.41k stars 99 forks source link

createReducer Allows Extra Keys To Be Added To State Without Errors #183

Open jstheoriginal opened 4 years ago

jstheoriginal commented 4 years ago

Description

createReducer allows you to add extra items to an object than what's on the defined state. It properly type-checks keys defined in the state type for the reducer...it just allows extra keys (not the end of the world, unless someone makes a spelling mistake).

Previously reported in the v5 thread, but it's confirmed to also be an issue in v4

Steps to Reproduce

Add an any item to a reducer object that isn't defined on the reducer's state type. Notice how TypeScript does not indicate that this is an issue. It would be easy for someone to make a spelling mistake of a key and then have no type checking, resulting in bugs.

Example (the extra property has no typescript errors reported..doing anything invalid to the other two properties properly shows errors):

export type AppState = {
  previous: string | null;
  current: string;
};

export type AppStateReducerState = {
  appState: AppState;
};

export const defaultAppReducerState: AppStateReducerState = {
  appState: {
    previous: null,
    current: 'active',
  },
};

export const appStateReducer = {
  appState: createReducer(defaultAppReducerState.appState).handleAction(
    setAppState,
    (state, { payload }) => ({
      previous: state.current,
      current: payload,
      extra: 'why is this allowed?',
    }),
  ),
};

CodeSandbox to help you reproduce issue in isolation https://codesandbox.io/embed/typesafe-actions-reference-project-7o6o1 (see src/store/example.ts)

Expected behavior

The extra key should not be allowed since it's not defined in the reducer's state type.

Suggested solution(s)

Show an error if any additional properties of state is provided.

Project Dependencies

piotrwitek commented 4 years ago

Hey @jstheoriginal

I can check if it is possible to make this a default behavior, but for now, you can simply add a return type constraint on the reducer handler to validate unknown keys.

Like this:

export const appStateReducer = {
  appState: createReducer(defaultAppReducerState.appState).handleAction(
    setAppState,
    (state, { payload }): AppState => ({
      previous: state.current,
      current: payload,
      extra: 'why is this extra key allowed?',
    })
  ),
};