Issue
I would like to make a class which stores some stuffs inside an object
class BusServiceFactory<T extends string = string> {
private readonly store: Record<T, Map<string, (val?: string) => unknown>> = {};
subscribe(uid: string, eventName: T, callback: (val?: string) => unknown): void {
this.store[eventName] ??= new Map();
this.store[eventName].set(uid, callback);
}
unsubscribe(uid: string): void {
Object.values(this.store).forEach((handler) => handler.delete(uid));
}
...
}
enum CustomEvent {
EventA = 'evtA',
EventB = 'evtB',
EventC = 'evtC',
}
export const CustomBus = new BusServiceFactory<CustomEvent>();
The main idea is to use a generic type for the key of store
so that I can pass an enum when I want to be exhaustive on the possible keys.
With that code, I got Type '{}' is not assignable to type 'Record<T, Map<string, (val?: string | undefined) => unknown>>'
on the line where I assign store
.
I get also 'handler' is of type 'unknown'
in the unsubscribe
method and I don't really understand why
Solution
The problem is that by saying store
is a Record<T, Map</*...*/>>
, you're requiring that it have properties for each possible value of T
, but {}
doesn't have any properties. You could work around that using Partial
, but I think for your use case, a Map
is a better fit (and it also solves the "handler
is of type unknown
" problem), see comments:
class BusServiceFactory<T extends string = string> {
// Changed this to a `Map`
private readonly store: Map<T, Map<string, (val?: string) => unknown>> = new Map();
subscribe(uid: string, eventName: T, callback: (val?: string) => unknown): void {
// Updated this because `this.store` is now a map
let entry = this.store.get(eventName);
if (!entry) {
entry = new Map();
this.store.set(eventName, entry);
}
entry.set(uid, callback);
}
unsubscribe(uid: string): void {
// And this
for (const entry of this.store.values()) {
entry.delete(uid);
}
}
// ...
}
Answered By - T.J. Crowder
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.