Skip to content

Commit

Permalink
fix(store): improve types for string selectors (#2174)
Browse files Browse the repository at this point in the history
  • Loading branch information
timdeschryver authored and brandonroberts committed Oct 28, 2019
1 parent 1b4ba1a commit 46a8467
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 136 deletions.
2 changes: 1 addition & 1 deletion modules/data/spec/selectors/entity-selectors$.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe('EntitySelectors$', () => {

// listen for changes to the hero collection
store
.select<HeroCollection>(ENTITY_CACHE_NAME, 'Hero')
.select<HeroCollection>(ENTITY_CACHE_NAME as any, 'Hero')
.subscribe((c: HeroCollection) => (collection = c));
});

Expand Down
2 changes: 1 addition & 1 deletion modules/router-store/src/router_store_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export class StoreRouterConnectingModule {
private setUpStoreStateListener(): void {
this.store
.pipe(
select(this.stateKey),
select(this.stateKey as any),
withLatestFrom(this.store)
)
.subscribe(([routerStoreState, storeState]) => {
Expand Down
90 changes: 0 additions & 90 deletions modules/store/spec/action_creator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createAction, props, union } from '@ngrx/store';
import { expecter } from 'ts-snippet';

describe('Action Creators', () => {
let originalTimeout: number;
Expand All @@ -13,17 +12,6 @@ describe('Action Creators', () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});

const expectSnippet = expecter(
code => `
// path goes from root
import {createAction, props, union} from './modules/store/src/action_creator';
${code}`,
{
moduleResolution: 'node',
target: 'es2015',
}
);

describe('createAction', () => {
it('should create an action', () => {
const foo = createAction('FOO', (foo: number) => ({ foo }));
Expand Down Expand Up @@ -54,45 +42,6 @@ describe('Action Creators', () => {

expect(JSON.parse(text)).toEqual({ type: 'FOO', foo: 42 });
});

it('should enforce ctor parameters', () => {
expectSnippet(`
const foo = createAction('FOO', (foo: number) => ({ foo }));
const fooAction = foo('42');
`).toFail(/not assignable to parameter of type 'number'/);
});

it('should enforce action property types', () => {
expectSnippet(`
const foo = createAction('FOO', (foo: number) => ({ foo }));
const fooAction = foo(42);
const value: string = fooAction.foo;
`).toFail(/'number' is not assignable to type 'string'/);
});

it('should enforce action property names', () => {
expectSnippet(`
const foo = createAction('FOO', (foo: number) => ({ foo }));
const fooAction = foo(42);
const value = fooAction.bar;
`).toFail(/'bar' does not exist on type/);
});

it('should not allow type property', () => {
expectSnippet(`
const foo = createAction('FOO', (type: string) => ({type}));
`).toFail(
/Type '{ type: string; }' is not assignable to type '"type property is not allowed in action creators"'/
);
});

it('should not allow ararys', () => {
expectSnippet(`
const foo = createAction('FOO', () => [ ]);
`).toFail(
/Type 'any\[]' is not assignable to type '"arrays are not allowed in action creators"'/
);
});
});

describe('empty', () => {
Expand Down Expand Up @@ -134,44 +83,5 @@ describe('Action Creators', () => {

expect(JSON.parse(text)).toEqual({ foo: 42, type: 'FOO' });
});

it('should enforce ctor parameters', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
const fooAction = foo({ foo: '42' });
`).toFail(/'string' is not assignable to type 'number'/);
});

it('should enforce action property types', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
const fooAction = foo({ foo: 42 });
const value: string = fooAction.foo;
`).toFail(/'number' is not assignable to type 'string'/);
});

it('should enforce action property names', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
const fooAction = foo({ foo: 42 });
const value = fooAction.bar;
`).toFail(/'bar' does not exist on type/);
});

it('should not allow type property', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ type: number }>());
`).toFail(
/Argument of type '"type property is not allowed in action creators"' is not assignable to parameter of type/
);
});

it('should not allow ararys', () => {
expectSnippet(`
const foo = createAction('FOO', props<[]>());
`).toFail(
/Argument of type '"arrays are not allowed in action creators"' is not assignable to parameter of type/
);
});
});
});
27 changes: 0 additions & 27 deletions modules/store/spec/reducer_creator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
import { on, createReducer, createAction, props, union } from '@ngrx/store';
import { expecter } from 'ts-snippet';

describe('classes/reducer', function(): void {
const expectSnippet = expecter(
code => `
// path goes from root
import {createAction, props} from './modules/store/src/action_creator';
import {on} from './modules/store/src/reducer_creator';
${code}`,
{
moduleResolution: 'node',
target: 'es2015',
}
);

describe('base', () => {
const bar = createAction('[foobar] BAR', props<{ bar: number }>());
const foo = createAction('[foobar] FOO', props<{ foo: number }>());

describe('on', () => {
it('should enforce action property types', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
on(foo, (state, action) => { const foo: string = action.foo; return state; });
`).toFail(/'number' is not assignable to type 'string'/);
});

it('should enforce action property names', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
on(foo, (state, action) => { const bar: string = action.bar; return state; });
`).toFail(/'bar' does not exist on type/);
});

it('should support reducers with multiple actions', () => {
const both = union({ bar, foo });
const func = (state: {}, action: typeof both) => ({});
Expand Down
95 changes: 95 additions & 0 deletions modules/store/spec/types/action_creator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { expecter } from 'ts-snippet';
import { compilerOptions } from './utils';

describe('createAction()', () => {
const expectSnippet = expecter(
code => `
import {createAction, props, union} from '@ngrx/store';
${code}
`,
compilerOptions()
);

describe('with props', () => {
it('should enforce ctor parameters', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
const fooAction = foo({ foo: '42' });
`).toFail(/'string' is not assignable to type 'number'/);
});

it('should enforce action property types', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
const fooAction = foo({ foo: 42 });
const value: string = fooAction.foo;
`).toFail(/'number' is not assignable to type 'string'/);
});

it('should enforce action property names', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
const fooAction = foo({ foo: 42 });
const value = fooAction.bar;
`).toFail(/'bar' does not exist on type/);
});

it('should not allow type property', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ type: number }>());
`).toFail(
/Argument of type '"type property is not allowed in action creators"' is not assignable to parameter of type/
);
});

it('should not allow ararys', () => {
expectSnippet(`
const foo = createAction('FOO', props<[]>());
`).toFail(
/Argument of type '"arrays are not allowed in action creators"' is not assignable to parameter of type/
);
});
});

describe('with function', () => {
it('should enforce ctor parameters', () => {
expectSnippet(`
const foo = createAction('FOO', (foo: number) => ({ foo }));
const fooAction = foo('42');
`).toFail(/not assignable to parameter of type 'number'/);
});

it('should enforce action property types', () => {
expectSnippet(`
const foo = createAction('FOO', (foo: number) => ({ foo }));
const fooAction = foo(42);
const value: string = fooAction.foo;
`).toFail(/'number' is not assignable to type 'string'/);
});

it('should enforce action property names', () => {
expectSnippet(`
const foo = createAction('FOO', (foo: number) => ({ foo }));
const fooAction = foo(42);
const value = fooAction.bar;
`).toFail(/'bar' does not exist on type/);
});

it('should not allow type property', () => {
expectSnippet(`
const foo = createAction('FOO', (type: string) => ({type}));
`).toFail(
/Type '{ type: string; }' is not assignable to type '"type property is not allowed in action creators"'/
);
});

it('should not allow arrays', () => {
expectSnippet(`
const foo = createAction('FOO', () => [ ]);
`).toFail(
/Type 'any\[]' is not assignable to type '"arrays are not allowed in action creators"'/
);
});
});
});
29 changes: 29 additions & 0 deletions modules/store/spec/types/reducer_creator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { expecter } from 'ts-snippet';
import { compilerOptions } from './utils';

describe('createReducer()', () => {
const expectSnippet = expecter(
code => `
import {createAction, props, on} from '@ngrx/store';
${code}
`,
compilerOptions()
);

describe('on()', () => {
it('should enforce action property types', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
on(foo, (state, action) => { const foo: string = action.foo; return state; });
`).toFail(/'number' is not assignable to type 'string'/);
});

it('should enforce action property names', () => {
expectSnippet(`
const foo = createAction('FOO', props<{ foo: number }>());
on(foo, (state, action) => { const bar: string = action.bar; return state; });
`).toFail(/'bar' does not exist on type/);
});
});
});
Loading

0 comments on commit 46a8467

Please sign in to comment.