Skip to content

Instantly share code, notes, and snippets.

@hungneox
Forked from elnygren/DI.py
Created August 12, 2021 15:01
Show Gist options
  • Save hungneox/eb60c170f29f25ec1ad69d59e874209e to your computer and use it in GitHub Desktop.
Save hungneox/eb60c170f29f25ec1ad69d59e874209e to your computer and use it in GitHub Desktop.
Functional Dependency Injection in TypeScript
# dataclass saves the trouble of writing __init__ implementations
# frozen=True makes the class instances immutable (so no hidden mutable state)
@dataclass(frozen=True)
class UserConnector:
def get_user(id: str) -> User:
return User.objects.get(id=id)
@dataclass(frozen=True)
class OrgConnector:
def get_org(id: str) -> Org:
return Org.objects.get(id=id)
@dataclass(frozen=True)
class UserService:
# we can pass default implementations here because they are immutable
# (would be dangerous if not as these would become shared for all instances of UserService)
user_connector: UserConnector = UserConnector()
org_connector: OrgConnector = OrgConnector()
def get_user_with_org(self, id: str) -> User:
return {
'user': self.user_connector.get_user(id),
'org': self.org_connector.get_org(id)
}
if __name__ == '__main__':
# can be parametrised with Mock user_connector and org_connector in tests
s = UserService()
user = s.get_user_with_org("123")
// Connector types (someone might call these DAO)
type UserConnector = {
getUser: (id: string) => User
}
type OrgConnector = {
getOrg: (id: string) => Org
}
// Dependencies for User Service
type UserServiceDeps = {
userConnector: UserConnector
orgConnector: OrgConnector
}
// "Factory" for user service, just use a closure+object literal (really more like a Record type here)
const makeUserService = ({ userConnector, orgConnector }: UserServiceDeps) => ({
getUserWithOrg() {
return {
user: userConnector.getUser(),
org: orgConnector.getOrg()
}
},
getUser() {
return userConnector.getUser()
}
})
function main() {
// these are probably in a different file, fancier, can also be parametrised
const userConnector = { getUser: (id) => { db.select('user').where({id}) }}
const orgConnector = { getOrg: (id) => { db.select('organisation').where({id}) }}
// build UserService, inject connectors
const UserService = makeUserService({ userConnector, orgConnector })
const user = UserService.getUserWithOrg()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment