TypeScript Inner Process Event Bus Example
Hey, I am currently trying to build an inner process event bus kind of thing and struggling with the types a bit.
Is there a way to describe all services (Context.Tag) which implement the same interface (here
Is there a way to describe all services (Context.Tag) which implement the same interface (here
EventHandler<UserCreated>EventHandler<UserCreated>)?import { Console, Context, Data, Effect, Layer, pipe } from 'effect';
type User = { id: number; name: string };
class EventHandlerError extends Data.TaggedError('EventHandlerError') {}
// events
interface DomainEvent {}
class UserCreated implements DomainEvent {
constructor(public readonly user: User) {}
}
// handlers
interface EventHandler<T extends DomainEvent> {
handle(domainEvent: T): Effect.Effect<void, EventHandlerError>;
}
class UserCreatedHandler1 implements EventHandler<UserCreated> {
handle(domainEvent: UserCreated) {
return Console.log(`[UserCreatedHandler1] received UserCreated event: ${domainEvent}`);
}
}
class UserCreatedHandler1Context extends Context.Tag('UserCreatedHandler1Context')<
UserCreatedHandler1Context,
UserCreatedHandler1
>() {
static readonly live = Layer.sync(UserCreatedHandler1Context, () => new UserCreatedHandler1());
}
class UserCreatedHandler2 implements EventHandler<UserCreated> {
handle(domainEvent: UserCreated) {
return Console.log(`[UserCreatedHandler2] received UserCreated event: ${domainEvent}`);
}
}
class UserCreatedHandler2Context extends Context.Tag('UserCreatedHandler2Context')<
UserCreatedHandler2Context,
UserCreatedHandler2
>() {
static readonly live = Layer.sync(UserCreatedHandler2Context, () => new UserCreatedHandler2());
}
const handler = [UserCreatedHandler1Context, UserCreatedHandler2Context];import { Console, Context, Data, Effect, Layer, pipe } from 'effect';
type User = { id: number; name: string };
class EventHandlerError extends Data.TaggedError('EventHandlerError') {}
// events
interface DomainEvent {}
class UserCreated implements DomainEvent {
constructor(public readonly user: User) {}
}
// handlers
interface EventHandler<T extends DomainEvent> {
handle(domainEvent: T): Effect.Effect<void, EventHandlerError>;
}
class UserCreatedHandler1 implements EventHandler<UserCreated> {
handle(domainEvent: UserCreated) {
return Console.log(`[UserCreatedHandler1] received UserCreated event: ${domainEvent}`);
}
}
class UserCreatedHandler1Context extends Context.Tag('UserCreatedHandler1Context')<
UserCreatedHandler1Context,
UserCreatedHandler1
>() {
static readonly live = Layer.sync(UserCreatedHandler1Context, () => new UserCreatedHandler1());
}
class UserCreatedHandler2 implements EventHandler<UserCreated> {
handle(domainEvent: UserCreated) {
return Console.log(`[UserCreatedHandler2] received UserCreated event: ${domainEvent}`);
}
}
class UserCreatedHandler2Context extends Context.Tag('UserCreatedHandler2Context')<
UserCreatedHandler2Context,
UserCreatedHandler2
>() {
static readonly live = Layer.sync(UserCreatedHandler2Context, () => new UserCreatedHandler2());
}
const handler = [UserCreatedHandler1Context, UserCreatedHandler2Context];