Skip to content
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

WIP - Complex Typings #90

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions devtools.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module "unistore/devtools" {
import { Store } from "unistore";
export default function devtools<TStoreState>(store: Store<TStoreState>): Store<TStoreState>;
}
2 changes: 1 addition & 1 deletion devtools.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = function unistoreDevTools(store) {
module.exports.default = function unistoreDevTools(store) {
var extension = window.__REDUX_DEVTOOLS_EXTENSION__ || window.top.__REDUX_DEVTOOLS_EXTENSION__;
var ignoreState = false;

Expand Down
38 changes: 13 additions & 25 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
// T - Wrapped component props
// S - Wrapped component state
// K - Store state
// I - Injected props to wrapped component
declare module "unistore" {
export type Action<TStoreState, TArgs extends any[]> = (state: TStoreState, ...args: TArgs) => Partial<TStoreState>;
export type BoundAction<TArgs extends any[]> = (...args: TArgs) => void;

export type Listener<K> = (state: K, action?: Action<K>) => void;
export type Unsubscribe = () => void;
export type Action<K> = (state: K, ...args: any[]) => void;
export type BoundAction = () => void;
export type Listener<TStoreState, TArgs extends any[]> = (state: TStoreState, action?: Action<TStoreState, TArgs>) => void;
export type Unsubscribe = () => void;

export interface Store<K> {
action(action: Action<K>): BoundAction;
setState(update: object, overwrite?: boolean, action?: Action<K>): void;
subscribe(f: Listener<K>): Unsubscribe;
unsubscribe(f: Listener<K>): void;
getState(): K;
}

export default function createStore<K>(state?: K): Store<K>;

export type ActionFn<K> = (state: K) => object;
export interface Store<TStoreState> {
action<TArgs extends any[]>(action: Action<TStoreState, TArgs>): BoundAction<TArgs>;

export interface ActionMap<K> {
[actionName: string]: ActionFn<K>;
setState<TArgs extends any[]>(update: object, overwrite?: boolean, action?: Action<TStoreState, TArgs>): void;
subscribe<TArgs extends any[]>(func: Listener<TStoreState, TArgs>): Unsubscribe;
unsubscribe<TArgs extends any[]>(func: Listener<TStoreState, TArgs>): void;
getState(): TStoreState;
}
export default function createStore<TStoreState>(state?: TStoreState): Store<TStoreState>;
}

export type ActionCreator<K> = (store: Store<K>) => ActionMap<K>;

export type StateMapper<T, K, I> = (state: K, props: T) => I;
76 changes: 62 additions & 14 deletions preact.d.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,70 @@
// T - Wrapped component props
// S - Wrapped component state
// K - Store state
// I - Injected props to wrapped component

declare module "unistore/preact" {
import * as Preact from "preact";
import { ActionCreator, StateMapper, Store } from "unistore";
import { Store } from "unistore";

// Diff / Omit taken from https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-311923766
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;

export interface ProviderProps<TStoreState> {
store: Store<TStoreState>;
}
export class Provider<IProps extends ProviderProps<TStoreState>, TStoreState> extends Preact.Component<IProps, {}> {
render(props: any, state: any): JSX.Element;
}

//Props

interface MapStateToProps<TStoreState, TExternalProps, TStoreProps> {
(state: TStoreState, ownProps: TExternalProps): TStoreProps;
}
type MapStateToPropsParam<TStoreState, TExternalProps, TStoreProps> = MapStateToProps<TStoreState, TExternalProps, TStoreProps> | null | undefined;

interface MapActionsToPropsFunction<TStoreState> {
[actionName: string]: (state: TStoreState, ...args: any[]) => Partial<TStoreState>;
}
interface MapActionsToPropsFactory<TStoreState, TActionProps> {
(store: Store<TStoreState>): TActionProps;
}
type MapActionsToPropsParam<TStoreState, TActionProps> = MapActionsToPropsFactory<TStoreState, TActionProps>;

type DefaultMapActionToProps<TStoreState> = { store: Store<TStoreState> }

export function connect<T, S, K, I>(
mapStateToProps: string | Array<string> | StateMapper<T, K, I>,
actions?: ActionCreator<K> | object
): (Child: (props: T & I) => Preact.VNode) => Preact.ComponentConstructor<T, S>;
interface FunctionalComponent<TProps> extends Preact.FunctionalComponent<TProps> { }
interface Component<TProps, TState> extends Preact.ComponentConstructor<TProps, TState> { }
type AnyComponent<PropsType, StateType> = FunctionalComponent<PropsType> | Component<PropsType, StateType>;

export interface ProviderProps<T> {
store: Store<T>;
interface InferableComponentEnhancerWithProps<TInjectedProps, TNeedProps> {
<TProps extends TInjectedProps, TState = {}>(
component: AnyComponent<TProps, TState>
): Preact.FunctionalComponent<Omit<TProps, keyof TInjectedProps> & TNeedProps> & { WrappedComponent: Preact.FunctionalComponent<TProps> }
}

export class Provider<T> extends Preact.Component<ProviderProps<T>, {}> {
render(props: ProviderProps<T>, {}): Preact.VNode;
type InferableComponentEnhancer<TInjectedProps> = InferableComponentEnhancerWithProps<TInjectedProps, {}>


export interface Connect {
(): InferableComponentEnhancer<DefaultMapActionToProps<any>>;

<TStoreProps={}, TExternalProps={}, TStoreState={}>(
mapStateToProps: MapStateToPropsParam<TStoreState, TExternalProps, TStoreProps>
): InferableComponentEnhancerWithProps<TStoreProps & DefaultMapActionToProps<TStoreState>, TExternalProps>;

<T extends string, TStoreProps={ [K in T]: any }, TExternalProps={}>(
mapStateToProps: T[]
): InferableComponentEnhancerWithProps<TStoreProps & DefaultMapActionToProps<any>, TExternalProps>;

<TStoreProps={}, TActionProps extends MapActionsToPropsFunction<TStoreState>={}, TActionPropsRemap = { [K in keyof TActionProps]: (...args) => void }, TExternalProps={}, TStoreState={}>(
mapStateToProps: MapStateToPropsParam<TStoreState, TExternalProps, TStoreProps>,
mapActionsToProps: MapActionsToPropsParam<TStoreState, TActionProps> | TActionProps
): InferableComponentEnhancerWithProps<TStoreProps & TActionPropsRemap, TExternalProps>;

<T extends string, TStoreProps={ [K in T]: any }, TActionProps extends MapActionsToPropsFunction<TStoreState>={}, TActionPropsRemap = { [K in keyof TActionProps]: (...args) => void }, TExternalProps={}, TStoreState={}>(
mapStateToProps: T[],
mapActionsToProps: MapActionsToPropsParam<TStoreState, TActionProps> | TActionProps
): InferableComponentEnhancerWithProps<TStoreProps & TActionPropsRemap, TExternalProps>;

}

export const connect: Connect;
}
66 changes: 57 additions & 9 deletions react.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,66 @@

declare module "unistore/react" {
import * as React from "react";
import { ActionCreator, StateMapper, Store } from "unistore";
import { Store } from "unistore";

export function connect<T, S, K, I>(
mapStateToProps: string | Array<string> | StateMapper<T, K, I>,
actions?: ActionCreator<K> | object
): (Child: (props: T & I) => React.ReactNode) => React.Component<T, S>;
// Diff / Omit taken from https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-311923766
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;

export interface ProviderProps<T> {
store: Store<T>;
export interface ProviderProps<TStoreState> {
store: Store<TStoreState>;
}

export class Provider<T> extends Component<ProviderProps<T>, {}> {
export class Provider<IProps extends ProviderProps<TStoreState>, TStoreState> extends React.Component<IProps, {}> {
render(): React.ReactNode;
}

//Props

interface MapStateToProps<TStoreState, TExternalProps, TStoreProps> {
(state: TStoreState, ownProps: TExternalProps): TStoreProps;
}
type MapStateToPropsParam<TStoreState, TExternalProps, TStoreProps> = MapStateToProps<TStoreState, TExternalProps, TStoreProps> | null | undefined;

interface MapActionsToPropsFunction<TStoreState> {
[actionName: string]: (state: TStoreState, ...args: any[]) => Partial<TStoreState>;
}
interface MapActionsToPropsFactory<TStoreState, TActionProps> {
<TActionProps>(store: Store<TStoreState>): TActionProps;
}
type MapActionsToPropsParam<TActionProps, TStoreState> = MapActionsToPropsFactory<TStoreState, TActionProps>; //| MapActionsToPropsFunction<TStoreState>;

type DefaultMapActionToProps<TStoreState> = { store: Store<TStoreState> }

interface FunctionalComponent<TProps> extends React.StatelessComponent<TProps> { }
interface Component<TProps, TState> extends React.Component<TProps, TState> { }
type AnyComponent<PropsType, StateType> = FunctionalComponent<PropsType> | Component<PropsType, StateType>;

interface InferableComponentEnhancerWithProps<TInjectedProps, TNeedProps> {
<TProps extends TInjectedProps, TState = {}>(
component: AnyComponent<TProps, TState>
): FunctionalComponent<Omit<TProps, keyof TInjectedProps> & TNeedProps> & { WrappedComponent: AnyComponent<TProps, TState> }
}

type InferableComponentEnhancer<TInjectedProps> = InferableComponentEnhancerWithProps<TInjectedProps, {}>


export interface Connect {
(): InferableComponentEnhancer<DefaultMapActionToProps<any>>;

<TStoreProps={}, TExternalProps={}, TStoreState={}>(
mapStateToProps: MapStateToPropsParam<TStoreState, TExternalProps, TStoreProps>
): InferableComponentEnhancerWithProps<TStoreProps & DefaultMapActionToProps<TStoreState>, TExternalProps>;

<T extends string, TStoreProps={ [K in T]: any }, TExternalProps={}>(
mapStateToProps: T[]
): InferableComponentEnhancerWithProps<TStoreProps & DefaultMapActionToProps<any>, TExternalProps>;

<TStoreProps={}, TActionProps extends MapActionsToPropsFunction<TStoreState>={}, TActionPropsRemap = { [K in keyof TActionProps]: (...args) => void }, TExternalProps={}, TStoreState={}>(
mapStateToProps: MapStateToPropsParam<TStoreState, TExternalProps, TStoreProps>,
mapActionsToProps: MapActionsToPropsParam<TActionProps, TStoreState>
): InferableComponentEnhancerWithProps<TStoreProps & TActionPropsRemap, TExternalProps>;

}

export const connect: Connect;
}