Parameters

Inject Runtime Values With Parameter.create()

Not every dependency is a class. Some values — user IDs, tenant IDs, request IDs, roles, config strings, feature flags — are only known at runtime. Use Parameter.create() to create injectable tokens for those values.

Defining and Injecting Parameters

Call Parameter.create("name") to produce a token. Inject it with @Inject(TOKEN) like any other dependency. Supply the value with TOKEN.value(someValue) at the resolution call site.

permissions.ts
import { Component, Inject, LoadAs, Parameter } from "@noego/ioc";

export const USER_ID = Parameter.create("userId");
export const USER_ROLE = Parameter.create("userRole");

@Component({ scope: LoadAs.Scoped })
export class CurrentUser {
  constructor(
    @Inject(USER_ID) readonly userId: string,
    @Inject(USER_ROLE) readonly role: "admin" | "member",
  ) {}
}

@Component({ scope: LoadAs.Scoped })
export class PermissionReader {
  constructor(
    @Inject(CurrentUser) private user: CurrentUser,
  ) {}

  canEdit(): boolean {
    return this.user.role === "admin";
  }
}

const root = createContainer();
const requestScope = root.extend();

const reader = await requestScope.instance(PermissionReader, [
  USER_ID.value("user-123"),
  USER_ROLE.value("admin"),
]);

Why Parameters Need Scoped State

A singleton is created once and reused. If a singleton consumes a runtime parameter, it can accidentally keep the first value it received. Request-specific values belong in scoped state so each request, page, or conversation gets its own instance.

Rules

  • Create one Parameter token per runtime value.
  • Parameter tokens are plain values — they don't need @Component.
  • Pass parameter values at the top-level resolution call using .value().
  • Keep parameter-consuming classes Scoped or Transient when values change per request.
  • Do not use parameters for dependencies that should be normal injected services.
NoEgo

© 2025 NoEgo. All rights reserved.