-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better typings for connect
#160
Comments
I think it would also make sense to make the |
I use another approach — I provide another signature for declare module 'unistore/preact' {
import { AnyComponent, ComponentConstructor } from 'preact';
import { ActionCreator, StateMapper, Store, ActionMap, ActionFn } from 'unistore';
type TupleTail<T extends any[]> = T['length'] extends 0
? never
: ((...tail: T) => void) extends (head: any, ...tail: infer I) => void
? I
: never;
type MakeBoundAction<K, F extends (...args: any) => ReturnType<ActionFn<K>>> = (
...args: TupleTail<Parameters<F>>
) => void;
type BoundActionFn<K> = MakeBoundAction<K, ActionFn<K>>;
export type ActionBinder<K, T extends object> = {
[P in keyof T]: BoundActionFn<T[P]>;
};
export function connect<T, S, K, I, A extends ActionMap<K>>(
mapStateToProps: string | string[] | StateMapper<T, K, I>,
actions: A | ((store: Store<K>) => A),
): (
Child: ComponentConstructor<T & I & ActionBinder<K, A>, S> | AnyComponent<T & I & ActionBinder<K, A>, S>,
) => ComponentConstructor<T | (T & I & ActionBinder<K, A>), S>;
} Benefits:
Drawbacks:
How it works: most of the magic happens in Example: interface AppState {
property: string;
}
function someAction(state: AppState, param: string): void {}
// Our component
interface OwnProps {
someProperty: string;
}
interface InjectedProps {
injectedProperty: string;
}
interface ActionProps extends ActionMap<AppState> {
someAction: typeof someAction;
}
type Props = OwnProps & InjectedProps & ActionBinder<AppState, ActionProps>;
type State = { /* ... */ };
class MyComponent extends Component<Props, State> { /* ... */ }
function mapStateToProps(state: AppState): InjectedProps { /* ... */ }
export const Extended = connect<OwnProps, State, AppState, InjectedProps, ActionProps>(
mapStateToProps,
{
someAction,
}
)(MyComponent); |
Hey,
using the current
connect
in typescript seems to give not as much type safety as possible. I came ob with these types/changes to make it more safe for us, as we had it more than once that we actually broke things without these types.This ensures a few things, maybe an example shows that better:
pickFromState
parameter fromsafeConnect
Store
and theComponentConnectedProps
actions
parameter fromsafeConnect
ComponentConnectedProps
State
) needs to match the one inComponentConnectedProps
Partial
of the stateThe one thing it can not ensure, is that all of the items from
ComponentConnectedProps
are there.Is there interest to get some version of this upstream?
The text was updated successfully, but these errors were encountered: