Skip to content

Instantly share code, notes, and snippets.

@carmanchris31
Last active February 11, 2021 01:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carmanchris31/6778dc94933ee4cbf86ce99f280afaca to your computer and use it in GitHub Desktop.
Save carmanchris31/6778dc94933ee4cbf86ce99f280afaca to your computer and use it in GitHub Desktop.
// Inspired by https://medium.com/@magnusjt/ioc-container-in-nodejs-e7aea8a89600
class UserModel {
isUser(): boolean {
return true
}
}
class UserService {
constructor(private model: UserModel) {}
doSomething(): void {}
}
class ContainerError extends Error {
name = 'ContainerError'
}
class Container<R extends Record<string, unknown> = {}> {
// @ts-expect-error
private factories: { [K in keyof R]: (instance: Container<R>) => R[K] } = {}
// @ts-expect-error
private resolved: { [K in keyof R]: R[K] } = {}
set<NewKey extends string, NewValue, NewRegistry extends Omit<R, NewKey> & Record<NewKey, NewValue>>(key: NewKey, factory: (instance: Container<R>) => NewValue): Container<NewRegistry> {
const newContainer = new Container<NewRegistry>()
// @ts-expect-error
newContainer.factories = {
...this.factories,
[key]: factory,
}
// @ts-expect-error
newContainer.resolved = {
...this.resolved,
[key]: undefined,
}
return newContainer
}
get<K extends keyof R>(key: K): R[K] {
if (this.resolved[key] === undefined) {
const resolved = this.factories[key](this)
if (resolved === undefined || resolved === null) {
throw new ContainerError(`Error building ${key}: received ${resolved}`)
}
this.resolved[key] = resolved
}
return this.resolved[key]
}
}
const container = new Container()
.set('SomeConstant', () => 4)
.set('SomeConstant', () => 'constant')
.set('UserModel', () => new UserModel())
.set('UserService', (instance) => new UserService(instance.get('UserModel')))
const model = container.get('UserModel');
const service = container.get('UserService');
const constant = container.get('SomeConstant');
console.log(model, service, constant)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment