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

export interface ImmerReducerFunction #46

Merged
merged 1 commit into from
Dec 12, 2019

Conversation

hcharley
Copy link
Contributor

@hcharley hcharley commented Dec 9, 2019

No description provided.

@esamattis
Copy link
Owner

This fixes #42?

@hcharley
Copy link
Contributor Author

hcharley commented Dec 9, 2019

Not completely, and sorry for the crpytic PR. This partially helped me.

I think the key is that either this file should export all of its contents, or have no exports--treating it as a declaration file. There may be some way to namespace it too. Truthfully i've never had to maintain a library before, so I'm probably not too much of a help here.

What I ultimately did just to stay focused on what I was trying to solve for my project, was to simply copy this file for my own uses, tweaking where I found it helpful for my usecase. Honestly, haven't even done a diff on this, so not sure which ones I left alone and which ones I modified:

import {
  ActionCreators,
  ImmerReducerClass,
  ImmerReducerState,
} from 'immer-reducer';
import { Dispatch } from 'react';

/** get function arguments as tuple type */
type ArgumentsType<T> = T extends (...args: infer V) => any ? V : never;

/**
 * Get the first value of tuple when the tuple length is 1 otherwise return the
 * whole tuple
 */
type FirstOrAll<T> = T extends [infer V] ? V : T;

/** Get union of function property names */
type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

type MethodObject = { [key: string]: () => any };

/** Pick only methods from object */
type Methods<T> = Pick<T, FunctionPropertyNames<T>>;

/** flatten functions in an object to their return values */
type FlattenToReturnTypes<T extends MethodObject> = {
  [K in keyof T]: ReturnType<T[K]>;
};

/** get union of object value types */
type ObjectValueTypes<T> = T[keyof T];

/** get union of object method return types */
type ReturnTypeUnion<T extends MethodObject> = ObjectValueTypes<
  FlattenToReturnTypes<T>
>;

export interface ImmerReducerFunction<T extends ImmerReducerClass> {
  (
    state: ImmerReducerState<T> | undefined,
    action: ReturnTypeUnion<ActionCreators<T>>
  ): ImmerReducerState<T>;
}

export type ImmerReducerFunctionObj<T extends ImmerReducerClass> = {
  state: ImmerReducerState<T> | undefined;
  action: ReturnTypeUnion<ActionCreators<T>>;
};

export type ImmerReducerFunctionObjReact<T extends ImmerReducerClass> = {
  state: ImmerReducerState<T> | undefined;
  dispatch: Dispatch<ReturnTypeUnion<ActionCreators<T>>>;
  actions: ActionCreators<T>;
};

export interface ImmerActionCreator<ActionTypeType, Payload extends any[]> {
  readonly type: ActionTypeType;

  (...args: Payload): {
    type: ActionTypeType;
    payload: FirstOrAll<Payload>;
  };
}

// export type ImmerReducerState<T> = T extends {
//   prototype: {
//       state: infer V;
//   };
// }

And my usecase:

import {
  ImmerReducerFunction,
  ImmerReducerFunctionObj,
  ImmerReducerFunctionObjReact,
} from './immer';
import { MyAppReducer } from './MyAppReducer';

export interface IMyAppState {
  name: string;
  todos: Todo[];
  featuredTodo: Todo;
  enabled: boolean;
}

export interface IMyAppActionType<
  ActionName extends string,
  ActionData extends Partial<IMyAppState>
> {
  type: ActionName;
  data: ActionData;
}

export type MyAppReducerObj = ImmerReducerFunctionObj<
  typeof MyAppReducer
>;
export type MyAppReducerReact = ImmerReducerFunctionObjReact<
  typeof MyAppReducer
>;
export type MyAppReducerState = MyAppReducerObj['state'];
export type MyAppReducerAction = MyAppReducerObj['action'];

export type MyAppReducerFunction = ImmerReducerFunction<
  typeof MyAppReducer
>;

@esamattis
Copy link
Owner

esamattis commented Dec 12, 2019

Have you tried setting "declaration": false, to your tsconfig.json? Unless you are doing a library with .d.ts exports it should be ok.

Gonna merge this neither way as it won't hurt anything.

@esamattis esamattis merged commit e806588 into esamattis:master Dec 12, 2019
@esamattis
Copy link
Owner

@hcharley
Copy link
Contributor Author

Thank you @esamattis !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants