Skip to content

Commit

Permalink
feat(store): use strict projectors for createFeature selectors
Browse files Browse the repository at this point in the history
Closes #3740

BREAKING CHANGES:

Projectors of selectors generated by createFeature are strongly typed.

BEFORE:

Projector function arguments of selectors generated by createFeature are not strongly typed:

```ts
const counterFeature = createFeature({
  name: 'counter',
  reducer: createReducer({ count: 0 }),
});

counterFeature.selectCount.projector
// type: (...args: any[]) => number
```

AFTER:

Projector function arguments of selectors generated by createFeature are strongly typed:

```ts
const counterFeature = createFeature({
  name: 'counter',
  reducer: createReducer({ count: 0 }),
});

counterFeature.selectCount.projector
// type: (featureState: { count: number; }) => number
```
  • Loading branch information
markostanimirovic committed Mar 16, 2023
1 parent cbdf524 commit a68cad2
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 20 deletions.
36 changes: 18 additions & 18 deletions modules/store/spec/types/feature_creator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ describe('createFeature()', () => {
snippet.toInfer('reducer', 'ActionReducer<State, Action>');
snippet.toInfer(
'selectProductsState',
'MemoizedSelector<Record<string, any>, State, DefaultProjectorFn<State>>'
'MemoizedSelector<Record<string, any>, State, (featureState: State) => State>'
);
snippet.toInfer(
'selectProducts',
'MemoizedSelector<Record<string, any>, string[] | null, DefaultProjectorFn<string[] | null>>'
'MemoizedSelector<Record<string, any>, string[] | null, (featureState: State) => string[] | null>'
);
snippet.toInfer(
'selectQuery',
'MemoizedSelector<Record<string, any>, string, DefaultProjectorFn<string>>'
'MemoizedSelector<Record<string, any>, string, (featureState: State) => string>'
);
snippet.toInfer(
'productsFeatureKeys',
Expand Down Expand Up @@ -107,11 +107,11 @@ describe('createFeature()', () => {
snippet.toInfer('reducer', 'ActionReducer<{ count: number; }, Action>');
snippet.toInfer(
'selectCounterState',
'MemoizedSelector<Record<string, any>, { count: number; }, DefaultProjectorFn<{ count: number; }>>'
'MemoizedSelector<Record<string, any>, { count: number; }, (featureState: { count: number; }) => { count: number; }>'
);
snippet.toInfer(
'selectCount',
'MemoizedSelector<Record<string, any>, number, DefaultProjectorFn<number>>'
'MemoizedSelector<Record<string, any>, number, (featureState: { count: number; }) => number>'
);
});

Expand Down Expand Up @@ -231,15 +231,15 @@ describe('createFeature()', () => {
snippet.toInfer('reducer', 'ActionReducer<BooksState, Action>');
snippet.toInfer(
'selectBooksState',
'MemoizedSelector<AppState, BooksState, DefaultProjectorFn<BooksState>>'
'MemoizedSelector<AppState, BooksState, (featureState: BooksState) => BooksState>'
);
snippet.toInfer(
'selectBooks',
'MemoizedSelector<AppState, Book[], DefaultProjectorFn<Book[]>>'
'MemoizedSelector<AppState, Book[], (featureState: BooksState) => Book[]>'
);
snippet.toInfer(
'selectLoadState',
'MemoizedSelector<AppState, LoadState, DefaultProjectorFn<LoadState>>'
'MemoizedSelector<AppState, LoadState, (featureState: BooksState) => LoadState>'
);
snippet.toInfer(
'booksFeatureKeys',
Expand Down Expand Up @@ -272,11 +272,11 @@ describe('createFeature()', () => {
snippet.toInfer('reducer', 'ActionReducer<State, Action>');
snippet.toInfer(
'selectFooState',
'MemoizedSelector<{ foo: State; }, State, DefaultProjectorFn<State>>'
'MemoizedSelector<{ foo: State; }, State, (featureState: State) => State>'
);
snippet.toInfer(
'selectBar',
'MemoizedSelector<{ foo: State; }, string, DefaultProjectorFn<string>>'
'MemoizedSelector<{ foo: State; }, string, (featureState: State) => string>'
);
});

Expand Down Expand Up @@ -446,11 +446,11 @@ describe('createFeature()', () => {
snippet.toInfer('reducer', 'ActionReducer<State, Action>');
snippet.toInfer(
'selectCounterState',
'MemoizedSelector<Record<string, any>, State, DefaultProjectorFn<State>>'
'MemoizedSelector<Record<string, any>, State, (featureState: State) => State>'
);
snippet.toInfer(
'selectCount',
'MemoizedSelector<Record<string, any>, number, DefaultProjectorFn<number>>'
'MemoizedSelector<Record<string, any>, number, (featureState: State) => number>'
);
snippet.toInfer(
'selectCounterState2',
Expand Down Expand Up @@ -500,11 +500,11 @@ describe('createFeature()', () => {
snippet.toInfer('reducer', 'ActionReducer<{ count: number; }, Action>');
snippet.toInfer(
'selectCounterState',
'MemoizedSelector<Record<string, any>, { count: number; }, DefaultProjectorFn<{ count: number; }>>'
'MemoizedSelector<Record<string, any>, { count: number; }, (featureState: { count: number; }) => { count: number; }>'
);
snippet.toInfer(
'selectCount',
'MemoizedSelector<Record<string, any>, number, DefaultProjectorFn<number>>'
'MemoizedSelector<Record<string, any>, number, (featureState: { count: number; }) => number>'
);
snippet.toInfer(
'selectSquaredCount',
Expand Down Expand Up @@ -551,7 +551,7 @@ describe('createFeature()', () => {
);
snippet.toInfer(
'selectCount2',
'MemoizedSelector<Record<string, any>, number, DefaultProjectorFn<number>>'
'MemoizedSelector<Record<string, any>, number, (featureState: { count1: number; count2: number; }) => number>'
);
snippet.toInfer(
'selectCount10',
Expand Down Expand Up @@ -598,11 +598,11 @@ describe('createFeature()', () => {

snippet.toInfer(
'selectCounter1State',
'MemoizedSelector<Record<string, any>, number, DefaultProjectorFn<number>>'
'MemoizedSelector<Record<string, any>, number, (featureState: number) => number>'
);
snippet.toInfer(
'selectCounter2State',
'MemoizedSelector<Record<string, any>, number, DefaultProjectorFn<number>>'
'MemoizedSelector<Record<string, any>, number, (featureState: number) => number>'
);
snippet.toInfer(
'counterFeature1Keys',
Expand All @@ -628,7 +628,7 @@ describe('createFeature()', () => {

snippet.toInfer(
'selectCounterState',
'MemoizedSelector<Record<string, any>, number, DefaultProjectorFn<number>>'
'MemoizedSelector<Record<string, any>, number, (featureState: number) => number>'
);
snippet.toInfer(
'counterFeatureKeys',
Expand Down
6 changes: 4 additions & 2 deletions modules/store/src/feature_creator_models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export type FeatureSelector<
> = {
[K in FeatureName as `select${Capitalize<K>}State`]: MemoizedSelector<
AppState,
FeatureState
FeatureState,
(featureState: FeatureState) => FeatureState
>;
};

Expand All @@ -26,6 +27,7 @@ export type NestedSelectors<
[K in keyof FeatureState &
string as `select${Capitalize<K>}`]: MemoizedSelector<
AppState,
FeatureState[K]
FeatureState[K],
(featureState: FeatureState) => FeatureState[K]
>;
};

0 comments on commit a68cad2

Please sign in to comment.