Skip to content

Instantly share code, notes, and snippets.

@laat
Last active February 8, 2020 15:40
Show Gist options
  • Save laat/ccb70e170c06d6d8718452925566205b to your computer and use it in GitHub Desktop.
Save laat/ccb70e170c06d6d8718452925566205b to your computer and use it in GitHub Desktop.
rxjs nullable modad-ish
import { ajax } from "rxjs/ajax";
import { BehaviorSubject, combineLatest } from "rxjs";
import { Nullable as N } from "./Nullable";
import { NullableArray as NA } from "./NullableArray";
interface Data {
next: string;
}
const hostname = new BehaviorSubject<null | string>(null);
const data$ = hostname.pipe(
N.map(host => `https://${host}/data.json`),
N.switchMap(url => ajax.getJSON<Data>(url))
);
const next$ = combineLatest([data$, hostname]).pipe(
NA.map(([data, host]) => `https://${host}${data.next}`),
N.switchMap(url => ajax.getJSON<Data>(url))
);
import { Observable, of } from "rxjs";
import { map, switchMap } from "rxjs/operators";
export class Nullable {
static isNotNull<T>(v: T): v is NonNullable<T> {
return v != null;
}
static bind = <T, R>(
project: (value: NonNullable<T>, index: number) => R
) => (value: T, index: number): R | null =>
Nullable.isNotNull(value) ? project(value, index) : null;
static bindObservable = <T, R>(
project: (value: NonNullable<T>, index: number) => Observable<R>
) => (value: T, index: number): Observable<R | null> =>
Nullable.isNotNull(value) ? project(value, index) : of(null);
static map = <T, R>(
project: (value: NonNullable<T>, index: number) => R,
thisArg?: any
) => map(Nullable.bind(project), thisArg);
static switchMap = <T, R>(
project: (x: NonNullable<T>, i: number) => Observable<R>,
thisArg?: any
) =>
switchMap<T, Observable<R | null>>(
Nullable.bindObservable(project),
thisArg
);
}
import { Nullable } from "./Nullable";
import { Observable, of } from "rxjs";
import { map, switchMap } from "rxjs/operators";
export type NonNullableArray<T extends ReadonlyArray<any>> = {
[K in keyof T]: T[K] extends infer V ? NonNullable<V> : never;
};
export class NullableArray {
static hasNoNull = <T extends ReadonlyArray<any>>(
xs: readonly T[]
): xs is NonNullableArray<T> => xs.every(Nullable.isNotNull);
static bind = <T extends ReadonlyArray<any>, R>(
project: (value: NonNullableArray<T>, index: number) => R
) => (value: T, index: number): R | null =>
NullableArray.hasNoNull<T>(value) ? project(value, index) : null;
static bindObservable = <T extends ReadonlyArray<any>, R>(
project: (value: NonNullableArray<T>, index: number) => Observable<R>
) => (value: T, index: number): Observable<R | null> =>
NullableArray.hasNoNull<T>(value) ? project(value, index) : of(null);
static map = <T extends ReadonlyArray<any>, R>(
project: (value: NonNullableArray<T>, index: number) => R,
thisArg?: any
) => map(NullableArray.bind(project), thisArg);
static switchMap = <T extends ReadonlyArray<any>, R>(
project: (value: NonNullableArray<T>, index: number) => Observable<R>,
thisArg?: any
) =>
switchMap<T, Observable<R | null>>(
NullableArray.bindObservable(project),
thisArg
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment