@fioc/strict
v1.1.0
Published
Type-safe DI for JS/TS with strict compile-time validation — an extension of @fioc/core for robust dependency management.
Readme
@fioc/strict
@fioc/strict is an extension of FIoC (Fluid Inversion Of Control) providing stricter type checking and compile-time validation for dependency injection in TypeScript/JavaScript applications. It enhances @fioc/core by enforcing safety rules to prevent runtime errors and type mismatches.
🔑 Key Advantages
- 🔒 Compile-time validation: Detect unregistered dependencies or duplicate tokens at compile time.
- 🛡️ Safe resolution: Resolving unregistered dependencies returns type
never. - 🚀 Strict factory validation: Ensure factory parameters match registered dependencies.
- 🧩 Composable containers: Merge strict containers while preserving type safety.
- 🛠️ Controlled replacements: Safely replace existing registrations with
replaceorreplaceFactory.
Unlike
@fioc/core, @fioc/strict focuses solely on compile-time guarantees and validation.
Installation
npm install @fioc/core @fioc/strict
# or
yarn add @fioc/core @fioc/strict
# or
pnpm add @fioc/core @fioc/strictQuick Example: Strict Registration & Resolving
import { buildStrictDIContainer } from "@fioc/strict";
import { createDIToken } from "@fioc/core";
interface ApiService {
getData: () => string;
}
const ApiServiceToken = createDIToken<ApiService>().as("ApiService");
const HttpApiService: ApiService = { getData: () => "Hello, World!" };
const container = buildStrictDIContainer()
.register(ApiServiceToken, HttpApiService)
.getResult();
const apiService = container.resolve(ApiServiceToken); // Type `never` if not registered
apiService.getData(); // "Hello, World!"Advanced Usage
Factories with Strict Validation
import { buildStrictDIContainer } from "@fioc/strict";
import { createDIToken } from "@fioc/core";
export const getDataUseCaseToken =
createDIToken<() => string>().as("getDataUseCase");
const getDataUseCaseFactory = (apiService: ApiService) => () =>
apiService.getData();
const container = buildStrictDIContainer()
.register(ApiServiceToken, HttpApiService)
.registerFactory(getDataUseCaseToken, {
// Type error if the token is already registered
dependencies: [ApiServiceToken], // Type error if not registered
factory: getDataUseCaseFactory,
})
.getResult();
const useCase = container.resolve(getDataUseCaseToken); // Type `never` if not registered
useCase();Replacing Registrations Safely
const newImplementation: ApiService = { getData: () => "New Data!" };
const container = buildStrictDIContainer()
.register(ApiServiceToken, HttpApiService)
.replace(ApiServiceToken, newImplementation) // Won't give type error
.replaceFactory(getDataUseCaseToken, {
dependencies: [ApiServiceToken],
factory: getDataUseCaseFactory,
})
.getResult();Contributing
Open issues or submit pull requests on GitHub. Include tests for behavioral changes.
License
MIT License. See LICENSE.
