Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Typescript] Reducer definition causes Typescript to fall with error #2424

Closed
miraage opened this issue May 25, 2017 · 4 comments
Closed

[Typescript] Reducer definition causes Typescript to fall with error #2424

miraage opened this issue May 25, 2017 · 4 comments

Comments

@miraage
Copy link

miraage commented May 25, 2017

Redux: 3.6.0
Typescript: 2.3.3
compilerOptions.noImplicitAny is set to true.

Redux has next definitions.

export interface Action {
  type: any;
}

export type Reducer<S> = <A extends Action>(state: S, action: A) => S;

Reducer:

interface AuthReducerState {
  user?: {
    id: number;
    email: string;
  };
}

export const authReducer: Reducer<AuthReducerState> = (state, action) => {
  switch (action.type) {
    default:
      return state;
  }
};

Errors:

TS7006: Parameter 'state' implicitly has 'any' type.
TS7006: Parameter 'action' implicitly has 'any' type.

If definitons would have been changed it would solve problem.

export interface Action {
  type: string;
  [key: any]: any;
}

export type Reducer<S> = (state: S, action: Action) => S;

Please explain what I do wrong.

@mindjuice
Copy link
Contributor

mindjuice commented May 25, 2017

Just had time for a quick look, but I think you just need to define the types of state and action in your reducer, since without definitions, they are implicitly any:

export const authReducer: Reducer<AuthReducerState> = (state: AuthReducerState, action: Action) => {

Of course as soon as you try to reference other fields in Action you will get another type error, so you need to make your own MyAction type that extends Action and use that the type in your reducer.

Changing Action as you suggested (with [key: string], any) would make Actions non-type-safe, so that wouldn't be good.

As a side note, I'm using typescript-fsa for nice type-safe actions and reducers.

@miraage
Copy link
Author

miraage commented May 26, 2017

@mindjuice the issue here is that I have to provide additional typedef for state and action while they should've been taken from Reducer<S>.

@jimsugg
Copy link

jimsugg commented Jun 28, 2017

It gets worse in Typescript 2.4. The Reducer declaration really breaks big time there due to the work they did on strict contravariance for callback parameters. See the following discussion on the Typescript Issues page: https://github.com/Microsoft/TypeScript/issues/16795.

At this point, the only way I see to make Redux work with Typescript 2.4 is to redefine the Reducer as you have noted above:

export type Reducer<S> = <A extends Action>(state: S, action: A) => S;

You can still create subclassed Actions for type checking.

@jimsugg
Copy link

jimsugg commented Jun 28, 2017

There's a pull request open for this: #2467

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants