) => Method
+
+type Sources = {
+ [key: string]: MethodCreator
+}
+type WrappedMethods = {
+ [key: string]: Method
+}
+
+function link(instance: React.Component
, sources: Sources): WrappedMethods {
+ const wrappedMethods: WrappedMethods = {
+ /* [keyof sources] -> wrappedMethods.method */
+ }
+ const map = new Map(/* sources.creator -> wrappedMethods.method */)
+
+ const dispatchState: DispatchState = (updater, callback) => {
+ instance.setState(updater, callback)
+ }
+ const prepareState: PreDispatch
= updater => {
+ updater(instance.props, instance.state)
+ }
+ const dispatch = {
+ for(createMethod: MethodCreator, ...otherArgs: ParametersOfReturnedFunction) {
+ const isFromSource = sourcesValues.includes(createMethod)
+ if (isFromSource) {
+ const method = map.get(createMethod)
+ const runnable = applyMiddlewares(method, otherArgs)
+ run(runnable)
+ }
+ },
+ prepare: prepareState,
+ state: dispatchState,
+ }
+
+ Object.entries(sources).forEach(([key, createMethod]) => {
+ const method = createMethod(dispatch)
+ wrappedMethods[key] = method
+ map.set(createMethod, method)
+ })
+
+ const sourcesValues = Object.values(sources)
+
+ return wrappedMethods
+}
+
+export default function connect(mapping: Sources) {
+ return function linkComponent(
+ ComponentClass: React.ComponentClass
+ ): React.ComponentClass {
+ return class AwesomeApp extends React.PureComponent {
+ static displayName = `Connected(${ComponentClass.name})`
+ static defaultProps = ComponentClass.defaultProps
+
+ state = {} as ExtraP
+ boundCore = link(this, mapping) as WrappedMethods
+
+ render() {
+ const props = Object.assign({}, this.props, this.boundCore, this.state)
+ return React.createElement(ComponentClass, props)
+ }
+ }
+ }
+}