Skip to content

Instantly share code, notes, and snippets.

@saulin18
Created April 30, 2026 12:58
Show Gist options
  • Select an option

  • Save saulin18/ce079d31f8ca240c325316880c6b6bfd to your computer and use it in GitHub Desktop.

Select an option

Save saulin18/ce079d31f8ca240c325316880c6b6bfd to your computer and use it in GitHub Desktop.
Type-safe TS service registry
type ServiceA = Service<"ServiceA"> & {
name: "ServiceA";
foo: () => void;
};
type ServiceB = Service<"ServiceB"> & {
name: "ServiceB";
bar: () => void;
};
type Service<T extends string> = {
__brand: T;
createdAt?: Date | null;
updatedAt?: Date | null;
deletedAt?: Date | null;
isDeleted?: boolean | null;
};
namespace WithAdditions {
class ServiceRegistry<T extends Record<string, Service<string>>> {
private constructor(private registry: T) {}
register<K extends string, S extends Service<string>>(
key: K,
service: S,
): ServiceRegistry<T & Record<K, S>> {
(this.registry as any)[key] = service;
return this as unknown as ServiceRegistry<T & Record<K, S>>;
}
get<K extends keyof T>(key: K): T[K] {
return this.registry[key];
}
static init(): ServiceRegistry<{}> {
return new ServiceRegistry({});
}
}
const serviceAInstance: ServiceA = {
__brand: "ServiceA",
name: "ServiceA",
foo: () => {
console.log("foo");
},
};
const serviceBInstance: ServiceB = {
__brand: "ServiceB",
name: "ServiceB",
bar: () => {
console.log("bar");
},
};
const registry = ServiceRegistry.init()
.register("ServiceA", serviceAInstance)
.register("ServiceB", serviceBInstance);
// const a = registry.get("ServiceA")
// const b = registry.get("ServiceB")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment