Skip to content

Functions

API functions exported by NeoSyringe.

defineBuilderConfig

typescript
function defineBuilderConfig(config: BuilderConfig): Container

Define a container configuration. At runtime without the build plugin, this throws an error. At build time, it's replaced with the generated container.

Parameters

NameTypeDescription
configBuilderConfigContainer configuration

Returns

Container - The generated container (after build)

Example

typescript
import { defineBuilderConfig, useInterface } from '@djodjonx/neosyringe';

export const container = defineBuilderConfig({
  name: 'AppContainer',
  injections: [
    { token: useInterface<ILogger>(), provider: ConsoleLogger },
    { token: UserService }
  ]
});

definePartialConfig

typescript
function definePartialConfig(config: PartialConfig): PartialConfig

Define a reusable partial configuration that can be extended by a defineBuilderConfig.

Parameters

NameTypeDescription
config.injectionsInjection[]Services provided by this partial
config.expectsany[]Tokens this partial expects from its host container

Returns

PartialConfig — The partial configuration

Example — basic partial

typescript
import { definePartialConfig, useInterface } from '@djodjonx/neosyringe';

export const loggingPartial = definePartialConfig({
  injections: [
    { token: useInterface<ILogger>(), provider: ConsoleLogger }
  ]
});

export const container = defineBuilderConfig({
  extends: [loggingPartial],
  injections: [{ token: UserService }]
});

Example — partial with expects (peer dependencies)

Use expects when a partial's services depend on tokens registered in the host container. Common in feature-first / DDD architectures where a shared kernel registers cross-cutting concerns.

typescript
// user/config.ts
export const userPartial = definePartialConfig({
  expects: [
    useInterface<ICacheClient>(),
    useInterface<ITokenService>(),
    useInterface<IIdGenerator>(),
  ],
  injections: [
    { token: Login },
    { token: Register },
    { token: GetMe },
  ]
});

// app/container.ts
export const appContainer = defineBuilderConfig({
  useContainer: sharedKernel,      // provides ICacheClient, ITokenService, IIdGenerator
  extends: [userPartial],
});

TIP

If the host builder does not provide a token declared in expects, the analyzer raises an error pointing to the builder — not the partial.


useInterface

typescript
function useInterface<T>(): InterfaceToken<T>

Create a token for an interface. At compile time, this generates a unique string ID.

Type Parameters

NameDescription
TThe interface type

Returns

InterfaceToken<T> - A token representing the interface

Example

typescript
import { useInterface } from '@djodjonx/neosyringe';

interface ILogger {
  log(msg: string): void;
}

interface IDatabase {
  query(sql: string): any[];
}

// In configuration
{
  injections: [
    { token: useInterface<ILogger>(), provider: ConsoleLogger },
    { token: useInterface<IDatabase>(), provider: PostgresDatabase }
  ]
}

// Resolution
const logger = container.resolve(useInterface<ILogger>());

useProperty

typescript
function useProperty<T, C extends Constructor<any> = Constructor<any>>(
  targetClass: C,
  paramName: string
): PropertyToken<T, InstanceType<C>>

Create a token for a primitive constructor parameter.

Type Parameters

NameDescription
TRequired. The primitive type (string, number, boolean)
CInferred from targetClass. Rarely needs to be explicit.

Parameters

NameTypeDescription
targetClassCThe class that has this parameter
paramNamestringThe parameter name

Returns

PropertyToken<T, InstanceType<C>> - A token for the primitive

Example

typescript
import { useProperty } from '@djodjonx/neosyringe';

class ApiService {
  constructor(
    private apiUrl: string,
    private timeout: number
  ) {}
}

// Only T needs to be explicit — C is inferred from the class argument
const apiUrl = useProperty<string>(ApiService, 'apiUrl');
const timeout = useProperty<number>(ApiService, 'timeout');

// In configuration
{
  injections: [
    { token: apiUrl, provider: () => 'https://api.example.com' },
    { token: timeout, provider: () => 5000 },
    { token: ApiService }
  ]
}

declareContainerTokens

typescript
function declareContainerTokens<T>(container: any): any

Declare tokens provided by a legacy container for type-safety and validation.

Type Parameters

NameDescription
TObject type mapping token names to types

Parameters

NameTypeDescription
containeranyThe legacy container instance

Returns

The container with declared types

Example

typescript
import { declareContainerTokens } from '@djodjonx/neosyringe';
import { container as tsyringeContainer } from 'tsyringe';

// Declare what tsyringe provides
const legacy = declareContainerTokens<{
  AuthService: AuthService;
  UserRepository: UserRepository;
}>(tsyringeContainer);

// Use in configuration
export const container = defineBuilderConfig({
  useContainer: legacy,
  injections: [
    { token: NewService }  // Can depend on AuthService, UserRepository
  ]
});

Container.resolve

typescript
resolve<T>(token: Token<T>): T

Resolve a service from the container. The return type is automatically inferred from the token.

Type Parameters

NameDescription
TThe service type (inferred automatically)

Parameters

NameTypeDescription
tokenToken<T>Class, interface token, or property token

Returns

T - The resolved instance with full type safety

Throws

Error - If the service is not found

Type Inference Examples

NeoSyringe provides complete type safety without any type assertions:

typescript
// ✅ Class token - Type: UserService
const userService = container.resolve(UserService);
userService.createUser('John'); // Full auto-completion

// ✅ Interface token - Type: ILogger
const logger = container.resolve(useInterface<ILogger>());
logger.log('Hello'); // Methods of ILogger available

// ✅ Property token - Type: string
const apiUrl = container.resolve(useProperty<string>(ApiService, 'apiUrl'));
apiUrl.toUpperCase(); // String methods available

// ✅ Generic classes - Type: Repository<User>
const userRepo = container.resolve(Repository<User>);
userRepo.findById(1); // Typed with User

Advanced Type Safety

typescript
// Dependencies are also fully typed
class UserService {
  constructor(
    private logger: ILogger,
    private repo: UserRepository
  ) {}
  
  async createUser(name: string) {
    // this.logger is typed as ILogger
    this.logger.log(`Creating user: ${name}`);
    // this.repo is typed as UserRepository
    return this.repo.save({ name });
  }
}

const service = container.resolve(UserService);
// Type: UserService
// All properties correctly typed!

No Type Assertions Needed

Unlike other DI libraries, you never need as or <Type> casts:

typescript
// ❌ Other libraries
const service = container.get('UserService') as UserService;

// ✅ NeoSyringe
const service = container.resolve(UserService);

Released under the MIT License.