Basic
Dependency Injection
Creating abstractions and implementations in Webiny
- How to create an abstraction in Webiny?
- How to create an implementation of an abstraction?
- How to declare dependencies?
- How to use the decorator pattern?
Overview
Webiny uses @webiny/di, a type-safe dependency injection container built for SOLID principles. The core concept is Abstraction<T>, which unifies tokens and types for compile-time safety. As a developer, you create implementations using createImplementation() and export them.
Creating an Abstraction
An abstraction is a type-safe token that represents an interface. Use createAbstraction() to create one:
Naming Convention:
- The abstraction name typically matches the interface name without the
Iprefix - Use a prefix to organize abstractions by domain (e.g.,
Library/BookRepository,Store/CreateOrder)
Namespace Pattern: Use a namespace with the same name as the abstraction to export related types. Export everything implementers will need - the interface, domain types, input/output types, etc. This allows consumers to use BookRepository.Interface and BookRepository.Book without additional imports.
Advanced Namespace Pattern
For more complex abstractions like use cases, you can organize additional types in the namespace:
This pattern allows consumers to reference all related types through the abstraction:
CreateBookUseCase.Interface- for implementing the use caseCreateBookUseCase.Input- for the input parametersCreateBookUseCase.Error- for error typesCreateBookUseCase.Return- for the return typeCreateBookUseCase.Book,CreateBookUseCase.Author,CreateBookUseCase.Category- domain types needed by implementers
Key Principle: Export everything an implementer needs. This creates a complete, self-contained abstraction where consumers only need to import the abstraction itself.
Creating an Implementation
Use createImplementation() from the abstraction to bind your class to it. This method is available on every abstraction and requires three properties:
With Dependencies
Dependencies are declared in the constructor and must match the dependencies array order:
Using Decorators
Decorators extend behavior without modifying the original implementation. Use createDecorator() from the abstraction to wrap existing functionality:
Key Point: The decorator’s last constructor parameter must be the type being decorated. The decoratee is automatically injected - you only list other dependencies in the dependencies array.
Key Points
Dependency Order Matters
The order in the dependencies array must exactly match the constructor parameter order:
Always Use .Interface Types
Constructor parameters should use the .Interface type from the abstraction:
Export the Implementation
Always export the result of createImplementation() or createDecorator():