Skip to content

Instantly share code, notes, and snippets.

@n1215
Last active April 21, 2021 06:49
Show Gist options
  • Save n1215/eb346762d43494dfc3f9eab2d7336e01 to your computer and use it in GitHub Desktop.
Save n1215/eb346762d43494dfc3f9eab2d7336e01 to your computer and use it in GitHub Desktop.
TypeScript classless DI container design
import { container, scopes } from "./library"
import { ListUsers, listUsersFactory } from "./listUsers"
import { UserRepositoryInterface } from "./UserRepoistoryInterface"
import { userRepositoryFactory } from "./userResistory"
const users = [{id: 1, name: "user1"}];
container.bind<UserRepositoryInterface>().toFactory(userRepositoryFactory, {users}).in(scopes.GLOBAL)
container.bind<ListUsers>().toFactory(listUsersFactory).in(scopes.GLOBAL)
import { ListUsers } from "./listUsers";
const requestHandlerFactory = ({
listUsers
}: {listUsers: ListUsers}) =>
(request: Request, response: Response): void => {
const users = listUsers();
response.send(users);
}
export default requestHandlerFactory;
export type Factory<T, Dep extends object> = ({...dependencies}: Dep) => T;
export type Scope = "global" | "request" | "transient";
export const scopes = {
GLOBAL: "global" as Scope,
REQUEST: "request" as Scope,
TRANSIENT: "transient" as Scope
}
export type Builder<T> = {
to(instance: T): Builder<T>
factory<Dep extends object>(factory: Factory<T, Dep>): Builder<T>
scope(scope: Scope): Builder<T>
}
const bind: <T>() => Builder<T> = <T>() => ({
to(): Builder<T> {
throw new Error("not implemented");
},
factory(): Builder<T> {
throw new Error("not implemented");
},
scope(): Builder<T> {
throw new Error("not implemented");
}
})
const get: <T>() => T = <T>() => {
throw new Error("not implemented");
}
export const container = {
get,
bind
}
import { UserRepositoryInterface } from "./UserRepoistoryInterface";
export const listUsersFactory = ({userRepository}: {userRepository: UserRepositoryInterface}) =>
() => userRepository.list()
export type ListUsers = ReturnType<typeof listUsersFactory>;
import { User, UserRepositoryInterface } from "./UserRepoistoryInterface";
export const userRepositoryFactory = ({users}: {users: User[]}) => (
{
list: () => users
}
)
export type User = {
id: number
name: string
}
export interface UserRepositoryInterface {
list(): User[]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment