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

Incorrect typescript typings for middlewares #2740

Closed
nenadalm opened this issue Nov 29, 2017 · 7 comments
Closed

Incorrect typescript typings for middlewares #2740

nenadalm opened this issue Nov 29, 2017 · 7 comments

Comments

@nenadalm
Copy link

Hi. It looks like typings don't work nicely for middlewares because I can't use type of state in it, because it's type is S (see the comment in code):

import * as redux from 'redux';

interface State {
    app: {
        title: string;
    }
}

const initialState: State = {
    app: {
        title: 'awesome app',
    }
}

function createMiddleware(): redux.Middleware {
    return function<S>(api: redux.MiddlewareAPI<S>) {
        return function (next: redux.Dispatch<S>): redux.Dispatch<S> {
            return function (action) {
                const state = api.getState();
                // error is shown here because `app` does not exist on type `S`
                console.log('app title: ', state.app.title);

                next(action);
            };
        };
    }
}

function appReducer(state: State, action) {
    return state;
}

redux.createStore(
    appReducer,
    initialState,
    redux.applyMiddleware(createMiddleware())
)

My colleague advised me to extend redux.Middleware but then typings don't work either because following code should fail to compile, but it compiles just fine (see the comment in code):

import * as redux from 'redux';

interface State {
    app: {
        title: string;
    }
}

export interface Middleware extends redux.Middleware {
    (api: redux.MiddlewareAPI<State>): (next: redux.Dispatch<State>) => redux.Dispatch<State>;
}

function createMiddleware(): Middleware {
    return function(api: redux.MiddlewareAPI<State>) {
        return function (next: redux.Dispatch<State>): redux.Dispatch<State> {
            return function (action) {
                const state = api.getState();
                // `state` is of type `State2` which doesn't have `app` property, but typescript happily compiles this
                console.log('app title: ', state.app.title);

                next(action);
            };
        };
    }
}

interface State2 {
    wtf: string;
}

const initialState2: State2 = {
    wtf: 'ttf'
}

function appReducer(state: State2, action) {
    return state;
}

redux.createStore(
    appReducer,
    initialState2,
    redux.applyMiddleware(createMiddleware())
)

environment:

  • redux: 3.7.2
  • typescript: 2.6.2

so applyMiddleware should probably take generic parameter for state and pass it to the middlewares?

// current definition
export function applyMiddleware(...middlewares: Middleware[]): GenericStoreEnhancer;

// should be probably defined something like:
export function applyMiddleware<S>(...middlewares: Middleware<S>[]): GenericStoreEnhancer;
@timdorr
Copy link
Member

timdorr commented Nov 29, 2017

I believe this is fixed in the 4.0 beta. I would try installing that and see if it fixes your issue.

@timdorr timdorr closed this as completed Nov 29, 2017
@nenadalm
Copy link
Author

@timdorr issue is the same. Updated message to work with 4.0.0-beta.1:

It looks like typings don't work nicely for middlewares because I can't use type of state in it, because it's type is S (see the comment in code):

import * as redux from 'redux';

interface State {
    app: {
        title: string;
    }
}

const initialState: State = {
    app: {
        title: 'awesome app',
    }
}

function createMiddleware(): redux.Middleware {
    return function<S, D>(api: redux.MiddlewareAPI<S, D>) {
        return function (next: redux.Dispatch<D>): redux.Dispatch<D> {
            return function <A extends D>(action: A): A {
                const state = api.getState();
                // error is shown here because `app` does not exist on type `S`
                console.log('app title: ', state.app.title);

                return next(action);
            };
        };
    }
}

function appReducer(state: State, action) {
    return state;
}

redux.createStore(
    appReducer,
    initialState,
    redux.applyMiddleware(createMiddleware())
)

My colleague advised me to extend redux.Middleware but then typings don't work either because following code should fail to compile, but it compiles just fine (see the comment in code):

import * as redux from 'redux';

interface State {
    app: {
        title: string;
    }
}

export interface Middleware extends redux.Middleware {
    <S extends State, D = redux.Action>(api: redux.MiddlewareAPI<S, D>): (next: redux.Dispatch<D>) => redux.Dispatch<D>;
}

function createMiddleware(): Middleware {
    return function<S, D>(api: redux.MiddlewareAPI<State>) {
        return function (next: redux.Dispatch<D>): redux.Dispatch<D> {
            return function <A extends D>(action: A): A {
                const state = api.getState();
                // `state` is of type `State2` which doesn't have `app` property, but typescript happily compiles this
                console.log('app title: ', state.app.title);

                return next(action);
            };
        };
    }
}

interface State2 {
    wtf: string;
}

const initialState2: State2 = {
    wtf: 'ttf'
}

function appReducer(state: State2, action) {
    return state;
}

redux.createStore(
    appReducer,
    initialState2,
    redux.applyMiddleware(createMiddleware())
)

environment:

  • redux: 4.0.0-beta.1
  • typescript: 2.6.2

so applyMiddleware should probably take generic parameter for state and pass it to the middlewares?

// current definition
export function applyMiddleware(...middlewares: Middleware[]): GenericStoreEnhancer;

// should be probably defined something like:
export function applyMiddleware<S>(...middlewares: Middleware<S>[]): GenericStoreEnhancer;

@timdorr timdorr reopened this Nov 29, 2017
@aikoven
Copy link
Collaborator

aikoven commented Dec 8, 2017

Just checking in to say that I'm going to take on this and other TypeScript typings issues for v4.0 during the next week.

Please don't release yet 😅

@timdorr
Copy link
Member

timdorr commented Dec 8, 2017

We can always do a 4.0.1 to bump up typings. Now that we're on TS 2.x, things should be smoother.

@timdorr
Copy link
Member

timdorr commented Dec 8, 2017

Note: I'm not planning on making 4.0 final any time soon.

@NathanNZ
Copy link

NathanNZ commented Feb 13, 2018

Would it be possible to give it another beta bump to push the latest changes in? #2773 has some really neat additions I'd like to try out (Middleware is generic!) 👍

@timdorr
Copy link
Member

timdorr commented Feb 15, 2018

@NathanNZ Just pushed 4.0.0-beta.2

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

No branches or pull requests

4 participants