-
Notifications
You must be signed in to change notification settings - Fork 110
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
Plugin methods #188
base: main
Are you sure you want to change the base?
Plugin methods #188
Conversation
packages/library/src/base/plugin.ts
Outdated
|
||
type PluginEvent = 'plugin:add' | 'plugin:remove' | ||
|
||
export class Plugin<C extends Component = Component, E = string> { | ||
async handle(context: C, event: E | PluginEvent, data?: any) {} | ||
export class Plugin< | ||
C extends Component = Component, | ||
E extends string = string, | ||
> { | ||
async handle(context: C, event: E | PluginEvent, ...params: any[]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dynamic dispatching implementation here is clever, I think there's a good way to do it in TS!
First off, it might be easier just to hardcode a handful of empty methods in this base class here and manually trigger them from the handle.
However, if you want to go full TypeScript wizard, it is now possible with Template Literal Types to perform string manipulation on keys within types. To say, define a number of on${Event}
methods computed from a union type of events. Here's a tsplayground where I play around with it: https://www.typescriptlang.org/play?#code/C4TwDgpgBAogbhAdsAcgQwLbQLxQOQBOAronlAD75gERho1mV5IAmeAUO6JLAsgBJpELADYQCAYRFoAzjKi4A3uyiqoAbQDWEEFACWiKAAMA9ogAkiiWjB7gaEXoBeEADzwkqTBAB8AXyMAXQAuKAAKAEoFHyg4Ez0Wdj9OAGNpOV5PAAURIgBzA1cJKAgAD2BWeQAjExMxIQAaWBLyyszkdCwYvQwwMSxkeQ8BIVFxKVl5ZTUoMwAlEkioZRU1ZJmzLJo6GiWVmfW1MxhhPc4DpKggA
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoa, thanks! I had no idea this was possible in TS, this is truly excellent. I'll see if I can incorporate your example, many thanks for that!
Given the limited number of intrinsic string manipulation types it probably makes sense to rename some events, specifically plugin:add
to pluginAdd
etc., but that strikes me as a good idea anyway; as far as I know that's the only place we use the good ol' backbone.js
event syntax. (those were the days!)
Hej @jdpigeon , I've attempted to add your template in 06ae4e1 -- if you have a moment, I'd super-appreciate your feedback! Overall, I really like the pattern and think that it could be a good model for components, too. That being said:
If we could make this work, I think it would be awesome, but right now I'm not fully convinced, but also not sure if the fallback is any better. Do you have thoughts? |
After playing around some more, let me maybe add a more concrete example. Here's what works: type EventHandlerClass<E, T> = {
[key in `on${Capitalize<EventName>}`]?: (whatever: T) => void
} Here's what I would like to do: type EventHandlerClass<E, T> = {
[key in `on${Capitalize<E>}`]?: (whatever: T) => void
} Notice the change in |
Ahhh, it does appear that there's a limitation to that pattern, and I don't think there's going to be a way around that one. Is it really important for Plugins to be able to handle new events that go beyond those in the standard Component life cycle (+ plugin:prepare, etc.)? Our custom plugins only ever handle 'prepare' 'run' and 'end'. If you do want to keep that flexibility open, I don't think it's a bad pattern to allow plugins to receive a generic string event name for the handle function, and still have the defaults used to populate the built-in methods. playground |
No description provided.