ngrx / core

Core functionality for the ngrx platform
MIT License
72 stars 25 forks source link

Compose function can't take an array of functions #19

Closed dotlouis closed 6 years ago

dotlouis commented 7 years ago

Hi, I just ran into an issue: When I call the compose function like this:

// this should return a root reducer;
return compose([
    ...metaReducers,
    combineReducers,
  ])(reducers)(state, action);
}

Typescript compiles but throws on execution because it fails at destructuring the array of functions thus register the argument as an array. But the compose signature says that i could use an array:

export interface ComposeSignature {
    <A>(): (i: A) => A;
    <A, B>(b: (i: A) => B): (i: A) => B;
    <A, B, C>(c: (i: B) => C, b: (i: A) => B): (i: A) => C;
    <A, B, C, D>(d: (i: C) => D, c: (i: B) => C, b: (i: A) => B): (i: A) => D;
    <A, B, C, D, E>(e: (i: D) => E, d: (i: C) => D, c: (i: B) => C, b: (i: A) => B): (i: A) => E;
    <A, B, C, D, E, F>(f: (i: E) => F, e: (i: D) => E, d: (i: C) => D, c: (i: B) => C, b: (i: A) => B): (i: A) => F;
    (...fns: any[]): (input: any) => any; // <== this line
}

Alright, you could say that I can destructure the array by myself or NOT put functions into any array in the first place like this:

return compose(
    ...metaReducers,
    combineReducers,
  )(reducers)(state, action);
}

But it causes Typescript >= 2.4 to throw on compile: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.

I found a workaround by doing so but it feels wrong to "cast" as any

return (compose(
    ...metaReducers,
    combineReducers,
  )(reducers) as any) (state, action);
}

The problem I think does not comes from your code because you do destructure functions: https://github.com/ngrx/core/blob/master/src/compose.ts#L12 So maybe the issue comes from the typscript compiler or maybe there is something I don't understand. Do you have any idea on what causes the array of function in the compose function not to work ?

nathanmarks commented 7 years ago

@dotlouis did you find a solution for this other than the workaround?

dotlouis commented 7 years ago

@nathanmarks Actually no, I'm still using the workaround, but this is the least bad solution I have found.

dotlouis commented 6 years ago

Now that ngrx@4 is out, we don't really have a use for the compose function since the StoreModule will take a map of reducers and an array meta-reducers. https://github.com/ngrx/platform/blob/master/docs/store/api.md#meta-reducers

I now do:

StoreModule.forRoot({
  state: someReducer
  }, {
    metaReducers: myMetaReducerArray,
}),