@tdi2/di-core
Version:
TypeScript Dependency Injection 2 - Core DI framework
55 lines (52 loc) • 2.05 kB
TypeScript
import { JSX } from 'react';
/**
* Marker interface for dependency injection in function parameters
* Usage: function MyComponent(services: {logger: Inject<LoggerInterface>}) {}
*/
type Inject<T> = T & {
readonly __inject__: unique symbol;
};
/**
* Marker type for optional dependency injection
* Usage: function MyComponent(services: {logger?: InjectOptional<LoggerInterface>}) {}
*/
type InjectOptional<T> = T & {
readonly __injectOptional__: unique symbol;
};
/**
* Service configuration for functional components
* This would be detected by the transformer for functions with this parameter shape
*/
interface ServiceDependencies {
[key: string]: Inject<any> | InjectOptional<any>;
}
/**
* Utility type to extract the actual types from Inject markers
*/
type ExtractServices<T extends ServiceDependencies> = {
[K in keyof T]: T[K] extends Inject<infer U> ? U : T[K] extends InjectOptional<infer U> ? U | undefined : never;
};
/**
* Function component with DI support
* This is what the transformer would look for and transform
*/
interface DIFunction<TServices extends ServiceDependencies, TProps = object> {
(props: TProps & {
services?: ExtractServices<TServices>;
}): JSX.Element;
}
/**
* Helper type for creating DI-enabled function components
* Example:
* const MyComponent: DIComponent<{logger: Inject<LoggerInterface>}, {title: string}> =
* ({title, services}) => { ... }
*/
type DIComponent<TServices extends ServiceDependencies, TProps = object> = DIFunction<TServices, TProps>;
/**
* Transform a regular React component to support DI
* This could be used as a higher-order function or detected by the transformer
*/
declare function withDI<TServices extends ServiceDependencies, TProps = object>(component: (props: TProps & {
services: ExtractServices<TServices>;
}) => JSX.Element, serviceConfig: TServices): React.ComponentType<TProps>;
export { type DIComponent, type DIFunction, type ExtractServices, type Inject, type InjectOptional, type ServiceDependencies, withDI };