Skip to content

Instantly share code, notes, and snippets.

@eneajaho
Last active May 12, 2024 07:25
Show Gist options
  • Save eneajaho/dd74aeecb877069129e269f912e6e472 to your computer and use it in GitHub Desktop.
Save eneajaho/dd74aeecb877069129e269f912e6e472 to your computer and use it in GitHub Desktop.
Initial computed$ implementation
import { Signal, isSignal } from "@angular/core";
import { toSignal, toObservable } from "@angular/core/rxjs-interop";
import { from, isObservable, Observable, ObservableInput, OperatorFunction } from "rxjs";
export function computed$<TValue, TReturn = TValue>(
signal: Signal<TValue>,
operator: OperatorFunction<TValue, TReturn>
): Signal<TReturn>;
export function computed$<TValue, TReturn = TValue>(
promise: Promise<TValue>,
initialValue: TValue,
operator?: OperatorFunction<TValue, TReturn>
): Signal<TReturn>;
export function computed$<TValue, TReturn = TValue>(
observable: Observable<TValue>,
initialValue?: TValue,
operator?: OperatorFunction<TValue, TReturn>
): Signal<TReturn>;
export function computed$<TValue, TReturn = TValue>(
source: ObservableInput<TValue> | Signal<TValue>,
initialValueOrOperator?: TValue | OperatorFunction<TValue, TReturn>,
operator?: OperatorFunction<TValue, TReturn>
): Signal<TReturn> {
const [$, op, initialValue] = toPipeableArgs(
source,
initialValueOrOperator,
operator
);
if (!op) {
return toSignal($, { initialValue }) as Signal<TReturn>;
}
return toSignal($.pipe(op), {
initialValue: initialValue as TReturn,
}) as Signal<TReturn>;
}
function toPipeableArgs<TValue, TReturn = TValue>(
source: ObservableInput<TValue> | Signal<TValue>,
initialValueOrOperator?: TValue | OperatorFunction<TValue, TReturn>,
operator?: OperatorFunction<TValue, TReturn>
): [Observable<TValue>, OperatorFunction<TValue, TReturn>?, TValue?] {
if (typeof source === "function" && isSignal(source)) {
return [
toObservable(source),
initialValueOrOperator as OperatorFunction<TValue, TReturn>,
source() as TValue,
];
}
if (
source instanceof Promise ||
("then" in source && typeof source["then"] === "function")
) {
if (
initialValueOrOperator === undefined ||
typeof initialValueOrOperator === "function"
)
throw new Error(`computed$ with Promise expects an initialValue`);
return [from(source), operator, initialValueOrOperator as TValue];
}
if (isObservable(source)) {
return [source, operator, initialValueOrOperator as TValue];
}
return [from(source), operator, initialValueOrOperator as TValue];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment