skip to content
Alvin Lucillo

Observable to signal initial value

/ 2 min read

Yesterday’s example showed how an observable is converted into signal, but when you look at the output, the first value is undefined, then it’s succeeded by 0 and so on. It’s undefined because at initialization/subscription, effect is triggered, but the observable has no value emitted on subscription, so the initial value is undefined.

If you want to ensure that the first value of an observable is not undefined, you can use requireSync, which when true will immediately check if the observable returns a value upon subscription. This creates a guard to ensure that before any processes happen, the value is not undefined.

// ...

injector = inject(Injector);

// ...

const nums$ = interval(1000);
const nums = toSignal(nums$, {
	injector: this.injector,
	requireSync: true,
});

effect(
	() => {
		console.log("nums", nums());
	},
	{
		injector: this.injector,
	},
);

However, you will encounter this error. The reason is because we still have undefined value on subscription.

ERROR RuntimeError: NG0601: `toSignal()` called with `requireSync` but `Observable` did not emit synchronously.
    at toSignal (rxjs-interop.mjs:244:11)
    at _TestComponent.onSearch (test.component.ts:71:18)
    at TestComponent_Template_input_keyup_enter_0_listener (

We can solve this by setting an initial value when we create an observable:

const nums$ = interval(1000).pipe(startWith(0));

Another way is to set an initial value when the signal is created:

const nums = toSignal(nums$, {
	injector: this.injector,
	// requireSync: true, // When initialValue is set, requireSync should not be set to true
	initialValue: 0,
});