Skip to content

Commit

Permalink
Cleans up and organises the typescript definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
ctrlplusb committed Jul 23, 2019
1 parent 0a06ee8 commit 78dc4d4
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 81 deletions.
209 changes: 130 additions & 79 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,14 @@ import {
StoreEnhancer,
Middleware,
} from 'redux';
import { string } from 'prop-types';

/**
* This allows you to narrow keys of an object type that are index signature
* based.
*
* Based on answer from here:
* https://stackoverflow.com/questions/56422807/narrowing-a-type-to-its-properties-that-are-index-signatures/56423972#56423972
*/
type IndexSignatureKeysOfType<A extends Object> = {
[K in keyof A]: A[K] extends ({ [key: string]: any } | { [key: number]: any })
? string extends keyof A[K]
? K
: number extends keyof A[K]
? K
: never
: never;
}[keyof A];

type ActionTypes = Action<any, any> | Thunk<any, any, any, any, any>;
// #region Helpers

type Meta = {
path: string[];
parent: string[];
};
export function actionName(action: Action<any, any>): string;

export function debug<StateDraft extends any>(state: StateDraft): StateDraft;

export function actionName(action: Action<any, any>): string;
export function memo<Fn extends Function = any>(fn: Fn, cacheSize: number): Fn;

export function thunkStartName(action: Thunk<any, any, any, any, any>): string;

Expand All @@ -58,6 +37,12 @@ export function thunkCompleteName(

export function thunkFailName(action: Thunk<any, any, any, any, any>): string;

// #endregion

// #region Actions

type ActionTypes = Action<any, any> | Thunk<any, any, any, any, any>;

type FilterActionTypes<T extends object> = Omit<
T,
KeysOfType<
Expand All @@ -70,11 +55,6 @@ type FilterActionTypes<T extends object> = Omit<
>
>;

type FilterStateTypes<T extends object> = Overwrite<
Omit<T, KeysOfType<T, Action<any, any> | Thunk<any, any, any, any, any>>>,
Pick<T, KeysOfType<T, Reducer<any, any>>>
>;

/**
* Filters a model into a type that represents the actions (and effects) only
*
Expand All @@ -99,6 +79,32 @@ export type Actions<Model extends Object> = {
: unknown;
};

// #endregion

// #region State

/**
* This allows you to narrow keys of an object type that are index signature
* based.
*
* Based on answer from here:
* https://stackoverflow.com/questions/56422807/narrowing-a-type-to-its-properties-that-are-index-signatures/56423972#56423972
*/
type IndexSignatureKeysOfType<A extends Object> = {
[K in keyof A]: A[K] extends ({ [key: string]: any } | { [key: number]: any })
? string extends keyof A[K]
? K
: number extends keyof A[K]
? K
: never
: never;
}[keyof A];

type FilterStateTypes<T extends object> = Overwrite<
Omit<T, KeysOfType<T, Action<any, any> | Thunk<any, any, any, any, any>>>,
Pick<T, KeysOfType<T, Reducer<any, any>>>
>;

type RequiredOnly<Model extends Object> = Pick<Model, RequiredKeys<Model>>;
type OptionalOnly<Model extends Object> = Pick<Model, OptionalKeys<Model>>;

Expand Down Expand Up @@ -150,6 +156,36 @@ export type State<Model extends Object> = FilterIndexSignatures<
FilterStateTypes<OptionalOnly<Model>>
>;

// #endregion

// #region Store + Config + Creation

/**
* Creates an easy-peasy powered Redux store.
*
* https://github.com/ctrlplusb/easy-peasy#createstoremodel-config
*
* @example
*
* import { createStore } from 'easy-peasy';
*
* interface StoreModel {
* todos: {
* items: Array<string>;
* }
* }
*
* const store = createStore<StoreModel>({
* todos: {
* items: [],
* }
* })
*/
export function createStore<
StoreModel extends Object = {},
StoreConfig extends EasyPeasyConfig<any, any> = any
>(model: StoreModel, config?: StoreConfig): Store<StoreModel, StoreConfig>;

/**
* Configuration interface for the createStore
*/
Expand All @@ -168,19 +204,7 @@ export interface EasyPeasyConfig<
reducerEnhancer?: (reducer: Reducer<any, any>) => Reducer<any, any>;
}

/**
* Enhances the Redux Dispatch with actions
*
* @example
*
* type DispatchWithActions = Dispatch<StoreModel>;
*/
export type Dispatch<
StoreModel,
Action extends ReduxAction = ReduxAction<any>
> = Actions<StoreModel> & ReduxDispatch<Action>;

export interface ActionData {
export interface MockedAction {
type: string;
[key: string]: any;
}
Expand All @@ -200,7 +224,7 @@ export type Store<
{
dispatch: Dispatch<StoreModel>;
getActions: () => Actions<StoreModel>;
getMockedActions: () => ActionData[];
getMockedActions: () => MockedAction[];
clearMockedActions: () => void;
useStoreActions: <Result = any>(
mapActions: (actions: Actions<StoreModel>) => Result,
Expand All @@ -213,6 +237,45 @@ export type Store<
}
>;

// #endregion

// #region Dispatch

/**
* Enhances the Redux Dispatch with actions
*
* @example
*
* type DispatchWithActions = Dispatch<StoreModel>;
*/
export type Dispatch<
StoreModel,
Action extends ReduxAction = ReduxAction<any>
> = Actions<StoreModel> & ReduxDispatch<Action>;

// #endregion

// #region Types for Thunk / Action listenTo configs

type Target<TargetPayload> =
| Action<any, TargetPayload>
| Thunk<any, TargetPayload>
| string
| void;

type ListenToTarget<TargetPayload> =
| Target<TargetPayload>
| Array<Target<TargetPayload>>;

// #endregion

// #region Thunk

type Meta = {
path: string[];
parent: string[];
};

/**
* A thunk type.
*
Expand Down Expand Up @@ -251,16 +314,6 @@ export type Thunk<
result: Result;
};

type Target<TargetPayload> =
| Action<any, TargetPayload>
| Thunk<any, TargetPayload>
| string
| void;

type ListenToTarget<TargetPayload> =
| Target<TargetPayload>
| Array<Target<TargetPayload>>;

/**
* Declares an thunk action type against your model.
*
Expand Down Expand Up @@ -300,6 +353,10 @@ export function thunk<
config?: { listenTo?: ListenTo },
): Thunk<Model, Payload, Injections, StoreModel, Result>;

// #endregion

// #region Action

/**
* An action type.
*
Expand Down Expand Up @@ -348,6 +405,10 @@ export function action<
},
): Action<Model, Payload>;

// #endregion

// #region Computed

type StateResolver<
Model extends {},
StoreModel extends {},
Expand Down Expand Up @@ -469,6 +530,10 @@ export function computed<
: void,
): Computed<Model, Result, ResolvedState, StoreModel>;

// #endregion

// #region Reducer

/**
* A reducer type.
*
Expand Down Expand Up @@ -510,31 +575,9 @@ export function reducer<State extends Object = {}>(
state: ReduxReducer<State>,
): Reducer<State>;

/**
* Creates an easy-peasy powered Redux store.
*
* https://github.com/ctrlplusb/easy-peasy#createstoremodel-config
*
* @example
*
* import { createStore } from 'easy-peasy';
*
* interface StoreModel {
* todos: {
* items: Array<string>;
* }
* }
*
* const store = createStore<StoreModel>({
* todos: {
* items: [],
* }
* })
*/
export function createStore<
StoreModel extends Object = {},
StoreConfig extends EasyPeasyConfig<any, any> = any
>(model: StoreModel, config?: StoreConfig): Store<StoreModel, StoreConfig>;
// #endregion

// #region Hooks

/**
* A React Hook allowing you to use state within your component.
Expand Down Expand Up @@ -591,6 +634,10 @@ export function useStoreDispatch<StoreModel extends Object = {}>(): Dispatch<
StoreModel
>;

// #endregion

// #region StoreProvider

/**
* Exposes the store to your app (and hooks).
*
Expand All @@ -610,6 +657,10 @@ export class StoreProvider<StoreModel = any> extends Component<{
store: Store<StoreModel>;
}> {}

// #endregion

// #region Context + Local Stores

interface StoreModelInitializer<
StoreModel extends Object = {},
InitialData = any
Expand Down Expand Up @@ -653,4 +704,4 @@ export function createComponentStore<
config?: StoreConfig,
): UseLocalStore<StoreModel, InitialData>;

export function memo<Fn extends Function = any>(fn: Fn, cacheSize: number): Fn;
// #endregion
4 changes: 2 additions & 2 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export const debug = state => {
return state;
};

export const memo = (fn, cacheSize) => memoizerific(cacheSize)(fn);

export const thunkStartName = action => `${action[actionNameSymbol]}(started)`;

export const thunkCompleteName = action =>
Expand All @@ -46,8 +48,6 @@ export const computed = (fn, stateResolvers = defaultStateResolvers) => {
return fn;
};

export const memo = (fn, cacheSize) => memoizerific(cacheSize)(fn);

export const thunk = (fn, config) => {
fn[thunkSymbol] = true;
fn[thunkStateSymbol] = {
Expand Down

0 comments on commit 78dc4d4

Please sign in to comment.