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

[use-global-hook] add UseGlobalActionTypes utility type #57263

Closed
no-stack-dub-sack opened this issue Nov 18, 2021 Discussed in #57260 · 1 comment
Closed

[use-global-hook] add UseGlobalActionTypes utility type #57263

no-stack-dub-sack opened this issue Nov 18, 2021 Discussed in #57260 · 1 comment

Comments

@no-stack-dub-sack
Copy link
Contributor

Discussed in #57260

Originally posted by no-stack-dub-sack November 18, 2021
Hello, the current use-gloabl-hook documentation on working with TypeScript shows the following for defining action types:

type MyAssociatedActions = {
  setValue: (value: string) => void;
  otherAction: (other: boolean) => void;
};

// setValue will be returned by globalHook as setValue.bind(null, store)
// This is one reason we have to declare a separate associated actions type
const setValue = (
  store: Store<MyState, MyAssociatedActions>,
  value: string
) => {
  store.setState({ ...store.state, value });
  store.actions.otherAction(true);
};

const otherAction = (
  store: Store<MyState, MyAssociatedActions>,
  other: boolean
) => { /* cool stuff */ };

This is problematic for applications with large numbers of actions (as noted by the comment in the example). Since the store argument is bound to the action function by the library, to represent your actions in the way that the library understands, you need to hand write the type for each action by omitting the first argument (as shown above), or come up with some other more elegant way to handle it so that you don't have to do this.

I'm proposing that a utility type be added to the type definitions for the library so that there's a consistent and easy way to handle this issue. This is just a quick sketch, but I think it can be accomplished by adding three types (inspired by TS's OmitThisParameter<T> utility type):

type StoreParameterType<T> = T extends (
  store: infer U,
  ...args: any[]
) => void | Promise<void>
  ? U
  : unknown;

type OmitStoreParameter<T> = T extends (
  store: StoreParameterType<T>,
  ...args: infer A
) => infer R
  ? (...args: A) => R
  : T;

type UseGlobalActionTypes<
  T extends { [key: string]: (...args: any[]) => any },
> = {
  [K in keyof T]: OmitStoreParameter<T[K]>;
};

Now, with the same actions as shown in the example above and in the docs, you can simply do:

const actions = {
  setValue,
  otherAction,
}

type RootActionTypes = UseGlobalActionTypes<typeof actions>;

// type RootActionTypes = {
//   setValue: (value: string) => void;
//   otherAction: (other: boolean) => void;
// }

// ^^ same exact type created manually in the documentation example

This would make typing large numbers of actions much simpler and super easy. Please let me know what you think. I'd be happy to put together a PR and discuss further.

@no-stack-dub-sack
Copy link
Contributor Author

closing after reading Moving DT issues to Discussions

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

No branches or pull requests

1 participant