Closed hcharley closed 4 years ago
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
>;
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.
Thank you @esamattis !
This fixes #42?