esamattis / immer-reducer

Type-safe and terse reducers with Typescript for React Hooks and Redux
http://npm.im/immer-reducer
MIT License
224 stars 15 forks source link

Type ImmerReducerFunction is not assignable to type 'Reducer<any>'. #16

Closed iamchanii closed 5 years ago

iamchanii commented 5 years ago

Hi. I faced type error using createReducerFunction.

My Code:

// AdminReducer.ts
import { ImmerReducer } from 'immer-reducer';

interface AdminState {
    foo: string;
}

class AdminReducer extends ImmerReducer<AdminState> {

}

export default AdminReducer;
// index.ts
import { createReducerFunction } from 'immer-reducer';
import { combineReducers } from 'redux';
import AdminReducer from './AdminReducer';

const admin = createReducerFunction(AdminReducer);

const createAdminReducer = () => {
    return combineReducers({
        admin, // <-- TS2322 Error
    });
};

export default createAdminReducer;

Typescript Error:

Error:(18, 9) TS2322: Type 'ImmerReducerFunction<typeof AdminReducer>' is not assignable to type 'Reducer<any>'.
  Types of parameters 'action' and 'action' are incompatible.
    Type 'AnyAction' is not assignable to type 'never'.

Could you take a look at my code that I missed any point? and is there any way to fix this problem exclude use as Reducer<any>? I think It may be a problem with the typescript version that I installed. so I attached my installed package versions.

Version:

typescript@3.2.2
immer-reducer@0.5.2
redux@3.7.2
esamattis commented 5 years ago

It seems that the error goes away when you define a method for the AdminReducer?

class AdminReducer extends ImmerReducer<AdminState> {
  foo() { }
}
iamchanii commented 5 years ago

I did it. I wrote some methods and use combineReducers() with as Reducer<any>. it looks good without any problems exclude that I used as Reducer<any> keyword.

class AdminReducer extends ImmerReducer<AdminState> {
    requestLogin(email: string, password: string) {
        this.draftState.loading = true;
    }

    loginSuccess() {
        this.draftState.auth.isLoggedIn = true;
    }

    // ...and 6 more methods.
}

and now, I still got an error. at least to me.

const admin = createReducerFunction(AdminReducer, adminInitialState);

const createAdminReducer = (history: History) => {
    return combineReducers<AppState>({
        admin, // <-- Error
        router: connectRouter(history),
    });
};
Error:(22, 9) TS2322: Type 'ImmerReducerFunction<typeof AdminReducer>' is not assignable to type 'Reducer<any>'.
  Types of parameters 'action' and 'action' are incompatible.
    Type 'AnyAction' is not assignable to type '{ type: "requestLogin"; payload: [string, string]; } | { type: "loginSuccess"; payload: []; } | { type: "logout"; payload: []; } | { type: "setLoading"; payload: [boolean]; } | { type: "showNotification"; payload: [...]; } | { ...; } | { ...; } | { ...; }'.
      Property 'payload' is missing in type 'AnyAction' but required in type '{ type: "unregisterResource"; payload: [string]; }'.
esamattis commented 5 years ago

Hmph. Not able to reproduce this. Can you post your tsconfig.json?

iamchanii commented 5 years ago

hmm, I can't find error today. it's only just past. now it is typed perfectly.

const admin = createReducerFunction(AdminReducer, adminInitialState);

const createAdminReducer = (history: History) => {
    return combineReducers<AppState>({
        admin,
        router: connectRouter(history),
    });
};

so I close issue. I will reopen if I got same error. thanks for your kind.

iamchanii commented 5 years ago

I forgot to post my tsconfig.json.

{
    "compilerOptions": {
        "target": "es5",
        "lib": [
            "dom",
            "dom.iterable",
            "esnext"
        ],
        "allowJs": true,
        "allowSyntheticDefaultImports": true,
        "downlevelIteration": true,
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "forceConsistentCasingInFileNames": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "module": "esnext",
        "moduleResolution": "node",
        "noEmit": true,
        "noImplicitAny": false,
        "resolveJsonModule": true,
        "skipLibCheck": true,
        "strict": true,
        "strictNullChecks": false
    },
    "include": [
        "src"
    ]
}