Skip to content

Instantly share code, notes, and snippets.

@justmoon
Created June 26, 2023 05:32
Show Gist options
  • Save justmoon/762361291fc1b43c7bd012b765de4f42 to your computer and use it in GitHub Desktop.
Save justmoon/762361291fc1b43c7bd012b765de4f42 to your computer and use it in GitHub Desktop.
Another idea for dependency injection with runtime access to the dependency tree
const makeComponent = <TDeps extends Dependencies, TProduct>(dependencies: TDeps, factory: (deps: ResolvedDependencies<TDeps>) => TProduct): SmartFactory<TProduct, TDeps> => {
const smartFactory = (predefinedDependencies = new Map()) => {
const resolvedDependencies: Partial<ResolvedDependencies<TDeps>> = {}
for (const key of Object.keys(dependencies)) {
if (predefinedDependencies.has(dependencies[key])) {
resolvedDependencies[key as keyof ResolvedDependencies<TDeps>] = predefinedDependencies.get(dependencies[key]) as ResolvedDependencies<TDeps>[string]
} else {
const resolvedDependency = dependencies[key](predefinedDependencies) as ResolvedDependencies<TDeps>[string]
resolvedDependencies[key as keyof ResolvedDependencies<TDeps>] = resolvedDependency
predefinedDependencies.set(dependencies[key], resolvedDependency)
}
}
return factory(resolvedDependencies as ResolvedDependencies<TDeps>)
}
smartFactory.dependencies = dependencies
return smartFactory
}
const Bar = makeComponent({}, () => {
return "This is Bar!"
})
const Foo = makeComponent({
bar: Bar
}, (dependencies) => {
console.log(dependencies.bar)
})
type ResolvedDependencies<TDeps extends Dependencies> = {
[K in keyof TDeps]: ReturnType<TDeps[K]>
}
type Dependencies = Record<string, SmartFactory<unknown, any>>
type Factory = (dependencies: Dependencies) => unknown
type SmartFactory<TProduct, TDeps extends Dependencies> = {
(predefinedDependencies?: Map<SmartFactory<unknown, any>, unknown>): TProduct
dependencies: TDeps
}
Foo()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment