Skip to main content
Version: Next

ServiceIdentifier

Overview

ServiceIdentifier is a fundamental type that identifies services within the InversifyJS dependency injection container. It serves as a key for registering, locating, and retrieving services, acting as a bridge between service registration and resolution.

Definition

ServiceIdentifier is a union type that can be one of:

type ServiceIdentifier<TInstance = unknown> =
| string
| symbol
| Newable<TInstance>
| AbstractNewable<TInstance>;

Where Newable is defined as:

type Newable<
TInstance = unknown,
TArgs extends unknown[] = any[],
> = new (...args: TArgs) => TInstance;

Usage

ServiceIdentifier is used throughout the InversifyJS API for:

  1. Service Registration: Binding services to the container
  2. Service Resolution: Retrieving services from the container
  3. Service Configuration: Setting activation/deactivation handlers

Examples

container.bind(UserService).toSelf();

// Using a string as a service identifier
container.bind('IUserService').to(UserService);

// Using a symbol as a service identifier
const userServiceId: ServiceIdentifier<UserService> = Symbol.for('UserService');
const castedUserServiceId: ServiceIdentifier<UserService> = Symbol.for(
'UserService',
) as ServiceIdentifier<UserService>;
container.bind(userServiceId).to(UserService);

// Resolving with a class identifier
const firstUserService = container.get(UserService);

// Resolving with a string identifier
const secondUserService = container.get('IUserService');

// Resolving with a symbol identifier
const thirdUserService = container.get(userServiceId);

// Resolving with a symbol identifier
const fourthUserService = container.get(castedUserServiceId);
Type Inference support

When using generics with ServiceIdentifier<T>, TypeScript can infer the resolved type. In the example above, firstUserService is automatically typed as UserService because UserService is inferred as ServiceIdentifier<UserService>.

Assignment reduced type

In TypeScript, when a variable annotated with a union is assigned, the actual initial type of that variable becomes "an assignment reduced type".

In the example above, userServiceId is automatically reduced as symbol and therefore, firstUserService is typed as unknown. Using a casting prevents this reduction and maintains the original type. Consider fourthUserService as an example.