Skip to content

Commit 303b7fe

Browse files
authored
Merge pull request reduxjs#1 from aikoven/next
Add tests for TS definitions
2 parents 14acd15 + f695975 commit 303b7fe

File tree

5 files changed

+340
-4
lines changed

5 files changed

+340
-4
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ node_js:
44
script:
55
- npm run lint
66
- npm run test:cov
7+
- npm run test:typescript
78
after_success:
89
- npm run coverage

index.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ interface ComponentDecorator<TOriginalProps, TOwnProps> {
1313
* - TStateProps: Result of MapStateToProps
1414
* - TDispatchProps: Result of MapDispatchToProps
1515
*/
16-
function connect<State, TOwnProps>(): ComponentDecorator<{ dispatch: Dispatch<State> } & TOwnProps, TOwnProps>;
16+
export function connect<State, TOwnProps>(): ComponentDecorator<{ dispatch: Dispatch<State> } & TOwnProps, TOwnProps>;
1717

18-
function connect<State, TOwnProps, TStateProps>(
18+
export function connect<State, TOwnProps, TStateProps>(
1919
mapStateToProps: FuncOrSelf<MapStateToProps<State, TOwnProps, TStateProps>>,
2020
): ComponentDecorator<TStateProps & { dispatch: Dispatch<State> } & TOwnProps, TOwnProps>;
2121

22-
function connect<State, TOwnProps, TStateProps, TDispatchProps>(
22+
export function connect<State, TOwnProps, TStateProps, TDispatchProps>(
2323
mapStateToProps: FuncOrSelf<MapStateToProps<State, TOwnProps, TStateProps>>|null,
2424
mapDispatchToProps: FuncOrSelf<MapDispatchToPropsFunction<State, TOwnProps, TDispatchProps> | MapDispatchToPropsObject & TDispatchProps>
2525
): ComponentDecorator<TStateProps & TDispatchProps & TOwnProps, TOwnProps>;
2626

27-
function connect<State, TOwnProps, TStateProps, TDispatchProps, TMergeProps>(
27+
export function connect<State, TOwnProps, TStateProps, TDispatchProps, TMergeProps>(
2828
mapStateToProps: FuncOrSelf<MapStateToProps<State, TOwnProps, TStateProps>>|null,
2929
mapDispatchToProps: FuncOrSelf<MapDispatchToPropsFunction<State, TOwnProps, TDispatchProps>| MapDispatchToPropsObject & TDispatchProps>,
3030
mergeProps: MergeProps<TOwnProps, TStateProps, TDispatchProps, TMergeProps>,

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"test": "cross-env BABEL_ENV=commonjs NODE_ENV=test mocha --compilers js:babel-register --recursive --require ./test/setup.js",
1919
"test:watch": "npm test -- --watch",
2020
"test:cov": "cross-env NODE_ENV=test nyc npm test",
21+
"test:typescript": "typings-tester --dir test/typescript",
2122
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov"
2223
},
2324
"repository": {
@@ -49,6 +50,7 @@
4950
},
5051
"homepage": "https://github.com/gaearon/react-redux",
5152
"devDependencies": {
53+
"@types/react": "^0.14.49",
5254
"babel-cli": "^6.3.17",
5355
"babel-core": "^6.3.26",
5456
"babel-eslint": "^6.1.2",
@@ -95,6 +97,8 @@
9597
"react-dom": "^0.14.0",
9698
"redux": "^3.0.0",
9799
"rimraf": "^2.3.4",
100+
"typescript": "^2.0.10",
101+
"typings-tester": "^0.2.0",
98102
"webpack": "^1.11.0"
99103
},
100104
"dependencies": {

test/typescript/test.tsx

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
import {Dispatch, Store} from "redux";
2+
import {connect, Provider} from "../../index";
3+
4+
5+
function testNoArgs() {
6+
const Connected = connect()(props => {
7+
// typings:expect-error
8+
props.foo;
9+
10+
return <button onClick={() => props.dispatch({type: 'CLICKED'})}/>;
11+
});
12+
13+
// typings:expect-error
14+
const c = <Connected foo="foo"/>;
15+
16+
const ConnectedWithProps = connect<{}, {foo: string}>()(props => {
17+
props.foo;
18+
return <button onClick={() => props.dispatch({type: 'CLICKED'})}/>;
19+
});
20+
21+
const cp = <ConnectedWithProps foo="foo"/>;
22+
23+
const connectorWithProps = connect<{}, {foo: string}>();
24+
25+
// typings:expect-error
26+
connectorWithProps((props: {bar: string}) => <div/>);
27+
}
28+
29+
30+
function testMapState() {
31+
type MyState = {foo: string, bar: number};
32+
33+
// typings:expect-error
34+
connect<MyState, {}, {}>((state: {baz: boolean}) => ({}));
35+
36+
const Connected = connect(
37+
(state: MyState, props: {baz: boolean}) => {
38+
return {
39+
foo: state.foo,
40+
fizz: props.baz,
41+
};
42+
},
43+
)(props => {
44+
const foo: string = props.foo;
45+
const baz: boolean = props.baz;
46+
const fizz: boolean = props.fizz;
47+
48+
// typings:expect-error
49+
props.bar;
50+
51+
props.dispatch({type: 'ACTION'});
52+
53+
return <div/>;
54+
});
55+
56+
// typings:expect-error
57+
<Connected/>;
58+
59+
<Connected baz/>;
60+
61+
// typings:expect-error
62+
<Connected baz="baz"/>;
63+
64+
const Connected2 = connect<MyState, {baz: boolean}, {foo: string, fizz: boolean}>(
65+
() => (state: MyState, props: {baz: boolean}) => {
66+
return {
67+
foo: state.foo,
68+
fizz: props.baz,
69+
};
70+
}
71+
)(props => {
72+
const foo: string = props.foo;
73+
const baz: boolean = props.baz;
74+
const fizz: boolean = props.fizz;
75+
76+
// typings:expect-error
77+
props.bar;
78+
79+
props.dispatch({type: 'ACTION'});
80+
81+
return <div/>;
82+
});
83+
84+
// typings:expect-error
85+
<Connected2/>;
86+
87+
<Connected2 baz/>;
88+
89+
// typings:expect-error
90+
<Connected2 baz="baz"/>;
91+
}
92+
93+
94+
function testMapDispatch() {
95+
type MyState = {foo: string};
96+
97+
const Connected = connect(
98+
(state: MyState) => {
99+
return {
100+
foo: state.foo,
101+
};
102+
},
103+
(dispatch: Dispatch<MyState>) => {
104+
return {
105+
handleClick() {
106+
dispatch({type: 'CLICKED'});
107+
},
108+
};
109+
},
110+
)(props => {
111+
const foo: string = props.foo;
112+
// typings:expect-error
113+
props.bar;
114+
115+
// typings:expect-error
116+
props.dispatch({type: 'TYPE'});
117+
118+
return <button onClick={props.handleClick}/>;
119+
});
120+
121+
<Connected/>;
122+
// typings:expect-error
123+
<Connected bar={42}/>;
124+
125+
type Props = {bar: number};
126+
const ConnectedWithProps = connect(
127+
(state: MyState) => {
128+
return {foo: state.foo};
129+
},
130+
(dispatch: Dispatch<MyState>, props: Props) => {
131+
return {
132+
handleClick() {
133+
dispatch({type: 'CLICKED', bar: props.bar});
134+
},
135+
};
136+
},
137+
)(props => {
138+
const foo: string = props.foo;
139+
const bar: number = props.bar;
140+
141+
// typings:expect-error
142+
props.dispatch({type: 'TYPE'});
143+
144+
return <button onClick={props.handleClick}/>;
145+
});
146+
147+
// typings:expect-error
148+
<ConnectedWithProps/>;
149+
150+
<ConnectedWithProps bar={42}/>;
151+
152+
const ConnectedWithDispatchObject = connect(
153+
(state: MyState) => {
154+
return {foo: state.foo};
155+
},
156+
{
157+
handleClick() {
158+
return {type: 'CLICKED'};
159+
},
160+
},
161+
)(props => {
162+
const foo: string = props.foo;
163+
// typings:expect-error
164+
props.bar;
165+
166+
// typings:expect-error
167+
props.dispatch({type: 'TYPE'});
168+
169+
return <button onClick={props.handleClick}/>;
170+
});
171+
172+
// typings:expect-error
173+
connect(
174+
null,
175+
{
176+
handleClick: () => 'not-an-action',
177+
},
178+
);
179+
180+
connect(
181+
null,
182+
{
183+
handleClick: () => (dispatch: Dispatch<MyState>) => {
184+
dispatch({type: 'SOME_ACTION'});
185+
},
186+
},
187+
);
188+
}
189+
190+
191+
function testMergeProps() {
192+
type MyState = {foo: string};
193+
194+
const connector = connect(
195+
(state: MyState) => {
196+
return {foo: state.foo};
197+
},
198+
(dispatch: Dispatch<MyState>) => {
199+
return {
200+
handleClick() {
201+
dispatch({type: 'CLICKED'});
202+
},
203+
};
204+
},
205+
(stateProps, dispatchProps) => {
206+
// typings:expect-error
207+
stateProps.bar;
208+
// typings:expect-error
209+
dispatchProps.foo;
210+
211+
return {stateProps, dispatchProps};
212+
}
213+
);
214+
215+
// typings:expect-error
216+
connector((props: {bar: number}) => <div/>);
217+
218+
const Connected = connector(props => {
219+
// typings:expect-error
220+
props.foo;
221+
// typings:expect-error
222+
props.handleClick;
223+
224+
const foo: string = props.stateProps.foo;
225+
226+
return <button onClick={props.dispatchProps.handleClick}/>;
227+
});
228+
229+
// typings:expect-error
230+
<Connected foo="fizz"/>;
231+
232+
<Connected/>;
233+
234+
type MyProps = {bar: number};
235+
236+
const Connected2 = connect(
237+
(state: MyState, props: MyProps) => {
238+
return {
239+
foo: state.foo,
240+
baz: props.bar,
241+
};
242+
},
243+
(dispatch: Dispatch<MyState>, props: MyProps) => {
244+
// typings:expect-error
245+
props.foo;
246+
247+
return {
248+
handleClick() {
249+
dispatch({type: 'CLICKED', bar: props.bar});
250+
},
251+
};
252+
},
253+
(stateProps, dispatchProps, ownProps) => {
254+
// typings:expect-error
255+
stateProps.bar;
256+
// typings:expect-error
257+
dispatchProps.bar;
258+
// typings:expect-error
259+
ownProps.foo;
260+
261+
return {
262+
fizz: stateProps.foo,
263+
bazz: stateProps.baz,
264+
buzz: ownProps.bar,
265+
clickHandler: dispatchProps.handleClick,
266+
}
267+
}
268+
)(props => {
269+
// typings:expect-error
270+
props.foo;
271+
// typings:expect-error
272+
props.baz;
273+
// typings:expect-error
274+
props.bar;
275+
// typings:expect-error
276+
props.handleClick;
277+
278+
const fizz: string = props.fizz;
279+
const bazz: number = props.bazz;
280+
const buzz: number = props.buzz;
281+
282+
return <button onClick={props.clickHandler}/>;
283+
});
284+
285+
// typings:expect-error
286+
<Connected2 foo="foo"/>;
287+
// typings:expect-error
288+
<Connected2 handleClick={() => {}}/>;
289+
// typings:expect-error
290+
<Connected2/>;
291+
292+
<Connected2 bar={1}/>;
293+
}
294+
295+
function testOptions() {
296+
// typings:expect-error
297+
connect(null, null, null, {pure: 1});
298+
// typings:expect-error
299+
connect(null, null, null, {withRef: 1});
300+
301+
connect(null, null, null, {pure: true});
302+
connect(null, null, null, {withRef: true});
303+
connect(null, null, null, {pure: true, withRef: true});
304+
305+
connect(
306+
(state: {foo: string}) => ({foo: state.foo}),
307+
null,
308+
null,
309+
{pure: true}
310+
);
311+
}
312+
313+
function testProvider() {
314+
// typings:expect-error
315+
<Provider/>;
316+
// typings:expect-error
317+
<Provider store=""/>;
318+
// typings:expect-error
319+
<Provider store={null}/>;
320+
321+
let store: Store<{}> = {} as Store<{}>;
322+
<Provider store={store}/>;
323+
}

test/typescript/tsconfig.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"compilerOptions": {
3+
"module": "commonjs",
4+
"jsx": "react",
5+
"noImplicitAny": true,
6+
"strictNullChecks": true
7+
}
8+
}

0 commit comments

Comments
 (0)