Reputation: 2362
I try to use selectors
from reselect library in my Redux app.
my selectors file looks:
import { createSelector } from 'reselect'
const postsSelectors = state => state.global.posts.allPostse;
export const getPosts = createSelector(
[ postsSelectors ],
(posts) => posts
);
and then I try to use in my component, like this:
const mapStateToProps = (state) => ({
posts: getPosts(state),
});
When I try to compile all of this, I got this error:
I'm guessing that with how I declare types for props, which currently looks like that:
interface Props{
posts(state: any): any
loadStories(): void;
};
Help me please resolve this issue. Thanks in advance.
Upvotes: 13
Views: 21974
Reputation: 698
In the [email protected]
generics typing signature slightly changed if you're using the typescript@≥4.2
. So now it needs to be specified as: createSelector<Selectors extends SelectorArray, Result>
<Selectors extends SelectorArray, Result>
export type Selector<
// The state can be anything
State = any,
// The result will be inferred
Result = unknown,
// There are either 0 params, or N params
Params extends never | readonly any[] = any[]
// If there are 0 params, type the function as just State in, Result out.
// Otherwise, type it as State + Params in, Result out.
> = [Params] extends [never]
? (state: State) => Result
: (state: State, ...params: Params) => Result
export type SelectorArray = ReadonlyArray<Selector>
Example:
// get all posts
export const selectPosts = (state: TState): TPostsState => state.posts;
// get new posts
export const selectNewPosts = createSelector<
[Selector<TState, TPostsState>],
TPostData[]
>(
selectPosts,
(posts) => posts.filter(({ type }) => type === 'new'),
);
But in general, for the newer TS, you should not specify types manually now, as they will be automatically inferred.
If you're getting TS4023: Exported variable 'X' has or is using the name '$CombinedState' from external module
, please refer to the Stackoverflow answer https://stackoverflow.com/a/43901135/10963661 or try to set "declaration": false
compiler option in the tsconfig.json
file.
Upvotes: 3
Reputation: 121
An example with more types:
type TPostData = {
type: string;
};
type TPostsState = TPostData[];
type TState = {
posts: TPostsState;
};
// get all posts
export const selectPosts = (state: TState): TPostsState => state.posts;
// get new posts
export const selectNewPosts = createSelector<
TState,
TPostsState,
TPostData[]>(
selectPosts,
(posts) => posts.filter(({ type }) => type === 'new'),
);
Result: You've got all posts with type parameter 'new'.
Upvotes: 12
Reputation: 3171
TypeScript is not expecting an array for the first argument. Just pass in your selector functions as arguments to createSelector, as in
export const getPosts = createSelector(
postsSelectors,
(posts) => posts
);
Upvotes: 6