Merge pull request #24210 from Pajn/master

[recompose]: Improve type inference of withHandlers
This commit is contained in:
Mine Starks
2018-03-23 16:05:44 -07:00
committed by GitHub
2 changed files with 63 additions and 8 deletions
+18 -5
View File
@@ -3,6 +3,7 @@
// Definitions by: Iskander Sierra <https://github.com/iskandersierra>
// Samuel DeSota <https://github.com/mrapogee>
// Curtis Layne <https://github.com/clayne11>
// Rasmus Eneman <https://github.com/Pajn>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.6
@@ -78,13 +79,25 @@ declare module 'recompose' {
// withHandlers: https://github.com/acdlite/recompose/blob/master/docs/API.md#withhandlers
type EventHandler = Function;
type HandleCreators<TOutter, THandlers> = {
[handlerName in keyof THandlers]: mapper<TOutter, EventHandler>;
// This type is required to infer TOutter
type HandleCreatorsStructure<TOutter> = {
[handlerName: string]: mapper<TOutter, EventHandler>;
};
type HandleCreatorsFactory<TOutter, THandlers> = (initialProps: TOutter) => HandleCreators<TOutter, THandlers>;
// This type is required to infer THandlers
type HandleCreatorsHandlers<TOutter, THandlers> = {
[P in keyof THandlers]: (props: TOutter) => THandlers[P];
};
type HandleCreators<TOutter, THandlers> =
& HandleCreatorsStructure<TOutter>
& HandleCreatorsHandlers<TOutter, THandlers>
type HandleCreatorsFactory<TOutter, THandlers> = (initialProps: TOutter) =>
HandleCreators<TOutter, THandlers>;
export function withHandlers<TOutter, THandlers>(
handlerCreators: HandleCreators<TOutter, THandlers> | HandleCreatorsFactory<TOutter, THandlers>
): InferableComponentEnhancerWithProps<TOutter & THandlers, TOutter>;
handlerCreators:
| HandleCreators<TOutter, THandlers>
| HandleCreatorsFactory<TOutter, THandlers>
): InferableComponentEnhancerWithProps<THandlers & TOutter, TOutter>;
// defaultProps: https://github.com/acdlite/recompose/blob/master/docs/API.md#defaultprops
export function defaultProps<T = {}>(
+45 -3
View File
@@ -120,10 +120,35 @@ function testWithHandlers() {
/>
)
const handlerNameTypecheckProof = withHandlers<OutterProps, HandlerProps>({
const handlerNameTypecheckProof = withHandlers<OutterProps, HandlerProps>({ // $ExpectError
onChange: () => () => {},
notAKeyOnHandlerProps: () => () => {}, // $ExpectError
notAKeyOnHandlerProps: () => () => {},
});
// The inner props should be fully inferrable
const enhancer3 = withHandlers({
onChange: (props: OutterProps) => (e: any) => {},
onSubmit: (props: OutterProps) => (e: React.MouseEvent<any>) => {},
});
const Enhanced3 = enhancer3(({onChange, onSubmit, out}) =>
<div onClick={onSubmit}>{out}</div>);
const rendered3 = (
<Enhanced3
out={42}
/>
)
const enhancer4 = withHandlers((props: OutterProps) => ({
onChange: (props) => (e: any) => {},
onSubmit: (props) => (e: React.MouseEvent<any>) => {},
}));
const Enhanced4 = enhancer4(({onChange, onSubmit, out}) =>
<div onClick={onSubmit}>{out}</div>);
const rendered4 = (
<Enhanced4
out={42}
/>
)
}
function testDefaultProps() {
@@ -220,7 +245,24 @@ function testWithStateHandlers() {
(props: OutterProps) => ({ counter: props.initialCounter }),
{ notAKeyOfUpdaters: (state, props) => n => ({ ...state, counter: state.counter + n ** props.power }), }, // $ExpectError
);
}
// The inner props should be fully inferrable
const enhancer2 = withStateHandlers(
(props: OutterProps) => ({ counter: props.initialCounter }),
{
add: (state, props) => n => ({ ...state, counter: state.counter + n ** props.power }),
},
);
const Enhanced2 = enhancer((props) =>
<div>
<div>{`Counts from: ${props.initialCounter}`}</div>
<div>{`Counter: ${props.counter}`}</div>
<div onClick={() => props.add(2)}></div>
</div>);
const rendered2 = (
<Enhanced initialCounter={4} power={2} />
);
}
function testWithReducer() {
interface State { count: number }