Defining shared system actions #5204
Unanswered
with-heart
asked this question in
Q&A
Replies: 1 comment 1 reply
-
I ended up defining the functions like this: type SubscribeFunction = ActionFunction<
MachineContext,
any,
any,
any,
any,
any,
any,
any,
never
>
export const subscribePreUpdate: SubscribeFunction = sendTo(
// @ts-expect-error implicit any for system
({ system }) => system.get('lifecycle-manager'),
({ self }) =>
({
type: 'register.update.pre',
ref: self,
}) satisfies RegisterUpdatePreEvent,
)
export const subscribeUpdate: SubscribeFunction = sendTo(
// @ts-expect-error implicit any for system
({ system }) => system.get('lifecycle-manager'),
({ self }) =>
({ type: 'register.update', ref: self }) satisfies RegisterUpdateEvent,
)
export const subscribePostUpdate: SubscribeFunction = sendTo(
// @ts-expect-error implicit any for system
({ system }) => system.get('lifecycle-manager'),
({ self }) =>
({
type: 'register.update.post',
ref: self,
}) satisfies RegisterUpdatePostEvent,
) This allows the functions to be used in The I was also able to define them using this style: export const subscribePreUpdate = sendTo<
MachineContext,
any,
any,
AnyActorRef,
any
>(
({ system }) => system.get('lifecycle-manager'),
// @ts-expect-error implicit any for self
({ self }) =>
({
type: 'register.update.pre',
ref: self,
}) satisfies RegisterUpdatePreEvent,
) but that just moves the Not sure there are really any good options here which is frustrating because it means we can't provide type safety for things shared across a system. Better than nothing though! |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I'm building a system that defines a
lifecycle-manager
machine which sends system lifecycle events (update.pre
,update
,update.post
) to subscribed listeners in a consistent loop:I'd like to allow actors in the system to subscribe to whichever events they need access to and be notified of the events at the appropriate point in the lifecycle. For example, I'd like the
renderer
to subscribe toupdate.pre
so it can clear the canvas before rendering anything andupdate.post
so it can draw each drawable to the canvas:As you can see,
renderer
has theentry
actionssubscribeUpdatePre
andsubscribeUpdatePost
. UsingsendTo
, it's not that difficult to implement subscription in my machine'ssetup
config:However, let's imagine this system is shared by many different actors, each of which would like to subscribe to some combination of the
update
,update.pre
, andupdate.post
events. This now becomes a significant amount of boilerplate as each actor'ssetup
config needs to implement the same exact subscribe actions.I'd like to be able to define generic implementations of those actions so that any actor in the system can re-use them. This would allow my system to avoid the boilerplate of each subscriber needing to implement the same subscription logic over and over again.
We can already achieve this thanks to
sendTo
+ callbacks for both theto
andeventOrExpr
params:But unfortunately, I haven't been able to find a way to make the generic types match up in a way that doesn't cause errors at the use site. When I drop these functions straight into
setup
forrendererMachine
(setup({ actions: { subscribePreUpdate, subscribePostUpdate } })
), I receive type errors like this:It's reporting errors because the generic
EventObject
used by thesendTo
function isn't assignable to the machine-specific event types used by the consuming actor.Here's a StackBlitz link showing these type errors: https://stackblitz.com/edit/github-vrnmq81x?file=src%2Frenderer.ts&view=editor
Ideally I'd like to get even more specific with these actions. For example, only a machine that includes
UpdateEvent
in thesetup.types.events
union should be able to usesubscribeUpdate
as an action. But for now, I think just figuring out how to use these for any actor would be a good start.Any ideas?
Beta Was this translation helpful? Give feedback.
All reactions