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

feat: Expose FunctionWithParametersType #2983

Closed
jordanpowell88 opened this issue Apr 2, 2021 · 8 comments · Fixed by #2988
Closed

feat: Expose FunctionWithParametersType #2983

jordanpowell88 opened this issue Apr 2, 2021 · 8 comments · Fixed by #2988
Assignees

Comments

@jordanpowell88
Copy link
Contributor

jordanpowell88 commented Apr 2, 2021

Describe any alternatives/workarounds you're currently using

Is there a way to expose FunctionWithParametersType? I have several needs to reference this Type but I am only able to access it by doing a deep import @ngrx/store/models/src/.

I tried the following scenario using Creator but I get the following error:

export interface DispachableAction<P extends unknown[], R = void> {
  dispatch: Creator<P, R>;
}

Type 'R' does not satisfy the constraint 'object'.

If so, is it possible to patch this in previous versions as well?

Other information:

If accepted, I would be willing to submit a PR for this feature

[ X] Yes (Assistance is provided if you need help submitting a pull request)
[ ] No

@brandonroberts
Copy link
Member

Before we add this, check to see if this response helps solve your issue. #2532 (comment)

@jrista
Copy link
Contributor

jrista commented Apr 9, 2021

I spent over an hour trying all of the publicly exposed types to get our types to work with NgRx. In the end, the only one that allowed all the typing to align was FunctionWithParametersType, which we currently deep import. The next closest type was Creator, which is publicly exposed, but for the life of me I couldn't get to work.

@jordanpowell88
Copy link
Contributor Author

To answer your question @brandonroberts , Alex's suggestions do not work for our use case actually. Would it be a big deal to expose that Type?

@brandonroberts
Copy link
Member

Maybe. Everything we export publicly makes it harder to change in the future if we need to because of external dependencies like this use case. That's why I asked if it could be achieved without doing so.

@jrista
Copy link
Contributor

jrista commented Apr 9, 2021

I'm pretty sure what we are trying to achieve cannot be done any other way. I've run through the gamut of types, and this was the only one that gave us proper compatibility with NgRx. I've actually run into this need a few times in the past, and always ended up deep importing. Basically, any time you want to do something that reflects the nature of the dispatch function, you need this type. It's a pretty foundational type to how actions and dispatching works.

@brandonroberts
Copy link
Member

@jrista So we can understand further, can you explain what you're actually trying to do? All actions already can be dispatched without having a dispatch in their signaure directly, so why is something custom needed here?

@jrista
Copy link
Contributor

jrista commented Apr 9, 2021

We are working on a simple library that makes it easier to use NgRx within Angular component templates. We have a simple utility function that creates a "dispatcher" function for a given action. We attach those dispatchers to the component class, so we can call them directly from within the template. Its a super tiny, light weight library, but it can save a fair amount of coding in applications.

This little utility function, in order to get it working with NgRx properly, requires the FunctionWithParametersType. I tried to use just the Creator, and also tried just about every other type I could get my hands on, even tried to create my own, and none of them would allow us to get past the typing errors when we tried to compile the code.

The one type that works is FunctionWithParametersType...I suspect, because Creator is kind of at a higher level than the level we are trying to operate at. What we are actually working with is a derivative of using a creator...not a creator itself...if that makes any sense.

@jrista
Copy link
Contributor

jrista commented Apr 9, 2021

export const smartDispatch = <
  T extends string = string,
  C extends Creator = Creator,
  P extends any[] = any[],
  // eslint-disable-next-line @typescript-eslint/ban-types
  R extends object = object
>(
  action: ActionCreator<T, C>
): FunctionWithParametersType<P, R> => {
  const dispatch = (...args: P): R => {
    const store = (InjectorLocator as any)._injector.get(Store);

    return store.dispatch(action(args));
  };
  return dispatch;
};

This is what I fiddled with for about an hour or so, before I finally settled on the FunctionWithParametersType. It allows us to create a function that will dispatch a particular action. We usually use this within a component to expose a "dispatcher" to the template:

export const refreshItemsButtonClicked = createAction('[MyComponent] (Refresh Items Button) Clicked');

@Component(...)
export class MyComponent {
  refresh = smartDispatch(refreshItemsButtonClicked);
}

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 a pull request may close this issue.

4 participants