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] Should input selectors' states be merged? #264

Closed
bancek opened this issue Jul 5, 2017 · 11 comments
Closed

[TypeScript] Should input selectors' states be merged? #264

bancek opened this issue Jul 5, 2017 · 11 comments

Comments

@bancek
Copy link

bancek commented Jul 5, 2017

I'm building a modular application (in TypeScript) that has isolated root app states for modules. My main application's state just extends all the modules.

The probem is I want to use selectors from different modules as input selectors. I could achieve that with explicit type casting but the code becomes very verbose.

I've forked the library to add input selectors' state and props merging but it breaks some existing tests.

master...bancek:master

First broken test:

createSelector(
       (state: {foo: string}) => state.foo,
-      (state: never, props: {bar: number}) => props.bar,
+      (state: {}, props: {bar: number}) => props.bar,
       (foo, bar) => ({foo, baz: bar}),
     )

never should be replaced with empty interface because FooModuleState & BarModuleState & never seems to become never.

Second broken test:

const selector2 = createSelector(
    (state) => state.foo,
    (state) => state.foo,
    (state) => state.foo,
    (state) => state.foo,
    (state) => state.foo,
    (state: State, props: Props) => props.bar,
    (foo1, foo2, foo3, foo4, foo5, bar) => ({
      foo1, foo2, foo3, foo4, foo5, bar,
    }),
  );

Default state type inference does not work anymore.

My use case example:

import { createSelector, Selector } from 'reselect';

interface FooState {
  a: number;
}

interface FooModuleState {
  foo: FooState;
}

interface BarState {
  b: number;
}

interface BarModuleState {
  bar: BarState;
}

interface AppState extends FooModuleState, BarModuleState {
  
}

const foo = (state: FooModuleState) => state.foo;
const a = createSelector(foo, foo => foo.a);

const bar = (state: BarModuleState) => state.bar;
const b = createSelector(bar, bar => bar.b);

// type error
const c = createSelector(a, b, (a, b) => a + b);

// this works
const c = createSelector(
  a as Selector<AppState, number>,
  b as Selector<AppState, number>,
  (a, b) => a + b
);
@aikoven
Copy link
Contributor

aikoven commented Jul 5, 2017

I think this is a viable proposal, although it would be a breaking change since type parameters are changed.

What if we include both old and new signatures? Would the tests pass then?

@aikoven
Copy link
Contributor

aikoven commented Jul 5, 2017

Also, why doesn't it work as is? AppState is assignable to both FooModuleState and BarModuleState. What error do you get?

@bancek
Copy link
Author

bancek commented Jul 5, 2017

The error is

The type argument for type parameter 'S' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
  Type argument candidate 'FooModuleState' is not a valid type argument because it is not a supertype of candidate 'BarModuleState'.
    Property 'foo' is missing in type 'BarModuleState'.

@bancek
Copy link
Author

bancek commented Jul 5, 2017

Including both old and new signatures works but tests are still broken.

I think the first test was broken from the beginning. It looks like the state is infered from the first input selector so if we switch order it doesn't work anyway.

This doesn't work:

   createSelector(
      (state: never, props: {bar: number}) => props.bar,
      (state: {foo: string}) => state.foo,
      (foo, bar) => ({foo, baz: bar}),
    )

@aikoven
Copy link
Contributor

aikoven commented Jul 5, 2017

Yep, I guess this is just a mistake in the test.

The only thing that bothers me is that the typings become extra bloated. Would be nice if we could someday generate all those signatures from a template.

Otherwise, I am 👍 for this change.

@seepel
Copy link

seepel commented Jul 25, 2017

I just encountered this and would love to get this fix. What are next steps for moving this forward?

@aikoven
Copy link
Contributor

aikoven commented Aug 8, 2017

Please help test the updated typings: #274

@seepel
Copy link

seepel commented Aug 14, 2017

I actually work with Ben, so minus some issues with typescript 2.4 I'm pretty confident of the typings :)

@blasterpistol
Copy link

@bancek @aikoven @seepel Any progress? faced the same problem.

@bancek
Copy link
Author

bancek commented Jan 9, 2018

@DenisNeustroev No progress from my side. We are using our own fork of the typings in our project.

@markerikson
Copy link
Contributor

Closing is this seems to be stale. If it's still a problem, please comment and we can discuss further.

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

No branches or pull requests

5 participants