Skip to content

assertInjector

Created by Chau Tran

assertInjector is an extension of assertInInjectionContext that accepts a Function and an optional custom Injector

assertInjector will assert that the Function is invoked in an Injection Context and will return a guaranteed Injector whether it is the custom one that is passed in or the default one.

import { assertInjector } from 'ngxtension/assert-injector';

Usage

assertInjector is mainly used for Custom Inject Functions (CIFs) or abstract functions that might depend on an Injection Context (i.e: effect() or takeUntilDestroyed()).

export function toSignal<T>(
observable: Observable<T>,
injector?: Injector,
): Signal<T> {
injector = assertInjector(toSignal, injector);
return runInInjectionContext(injector, () => {
const source = signal<T>(undefined!);
effect((onCleanup) => {
const sub = observable.subscribe((value) => {
source.set(value);
});
onCleanup(() => sub.unsubscribe());
});
return source.asReadonly();
});
}

Assert and run

assertInjector can also accept a runner which is a function that will be invoked in the Injection Context of the guaranteed Injector that it asserts. This usage shortens the CIF by not having to call runInInjectionContext explicitly.

export function toSignal<T>(
observable: Observable<T>,
injector?: Injector,
): Signal<T> {
return assertInjector(toSignal, injector, () => {
const source = signal<T>(undefined!);
effect((onCleanup) => {
const sub = observable.subscribe((value) => {
source.set(value);
});
onCleanup(() => sub.unsubscribe());
});
return source.asReadonly();
});
}

Retrieve the asserted Injector

Since the runner is invoked with the asserted Injector context, we can retrieve that Injector with inject(Injector) in the runner body. For example, nested effect() might need the Injector

export function injectFoo(injector?: Injector) {
return assertInjector(injectFoo, injector, () => {
const assertedInjector = inject(Injector);
// 👇 the outer effect automatically runs in the Injection Context
effect(() => {
/* do something for outer effect */
effect(
() => {
/* do something for inner effect */
},
{ injector: assertedInjector },
);
});
return 'foo';
});
}