Size / Priority
- Size: S (~50 lines)
- Category: C.3 Type-Safety.
- Risk: medium — pub-sub API surface change.
Affected files
src/cluster/pubsub/DistributedPubSubMediator.ts — Subscribe/Publish messages typed ActorRef without payload type.
src/cluster/pubsub/Messages.ts — message classes.
Background
DistributedPubSubMediator's Subscribe(topic, ref) accepts ActorRef<unknown> (or ActorRef<any>). The published payload is untyped — anything could land in the subscriber's mailbox under the topic.
Typed pubsub: associate a payload type with a topic. Subscribers receive correctly-typed messages.
Target
Phantom-typed topic wrapper:
// src/cluster/pubsub/Topic.ts (new)
/** Typed topic — payload type associated. */
export class Topic<T> {
constructor(public readonly name: string) {}
/** Phantom marker — never read at runtime. */
declare readonly _payloadType: T;
}
// Usage:
const UserEventsTopic = new Topic<UserEvent>('user-events');
mediator.tell(new Subscribe(UserEventsTopic, subscriberRef)); // subscriberRef typed ActorRef<UserEvent>
mediator.tell(new Publish(UserEventsTopic, { kind: 'created', userId: '42' })); // payload narrowed
Subscribe and Publish become generic:
export class Subscribe<T> {
constructor(public readonly topic: Topic<T>, public readonly ref: ActorRef<T>) {}
}
export class Publish<T> {
constructor(public readonly topic: Topic<T>, public readonly message: T) {}
}
Integration / risk
- API change —
Subscribe(string, ref) no longer compiles; must use Topic.
- Cross-language compat unaffected — wire format unchanged.
- Migration path: provide a backward-compat untyped variant + deprecation warning.
Test plan
- Per-site type-check — subscribers receive typed messages.
- Wire-format: published messages unchanged on the wire.
- Compile-time: mismatched payload types caught.
Acceptance criteria
Size / Priority
Affected files
src/cluster/pubsub/DistributedPubSubMediator.ts— Subscribe/Publish messages typedActorRefwithout payload type.src/cluster/pubsub/Messages.ts— message classes.Background
DistributedPubSubMediator'sSubscribe(topic, ref)acceptsActorRef<unknown>(orActorRef<any>). The published payload is untyped — anything could land in the subscriber's mailbox under the topic.Typed pubsub: associate a payload type with a topic. Subscribers receive correctly-typed messages.
Target
Phantom-typed topic wrapper:
SubscribeandPublishbecome generic:Integration / risk
Subscribe(string, ref)no longer compiles; must useTopic.Test plan
Acceptance criteria
Topic<T>exported.T.