Search code examples
rxjsrxjs7

Unable to remove null from observable array


Even though I've defined a type guard filter, I can't seem to get rid of my null observables. I defined my type guard:

export const hasValue = <T>(value: T): value is NonNullable<T> => value !== null && value !== undefined

and then my methods that want to filter like so:

#validateDocument(document: IDocument): Observable<AcmsDocumentBad | null> { ... }

validateDocuments(documents: IDocument[]): Observable<AcmsDocumentBad[]> {
    const observables = documents
        .filter(x => x.approvedSor === 'ACMS')
        .map(this.#validateDocument)

    return forkJoin(observables)
        .pipe(filter(hasValue))
}

I had expected that uses the pipe like that would result in Observable<AcmsDocumentBad[]> as the type, but it's still showing as Observable<(AcmsDocumentBad | null)[]>


Solution

  • forkJoin(Array<Observable<AcmsDocumentBad | null>>) returns an Observable<Array<AcmsDocumentBad | null>>, which emits an array with all the results just once, when all of the inner observables have completed.

    If you do .pipe(filter(hasValue)) on this, the result will be the same, because the observable never emits nulls, it will emit just one Array, guaranteed. The inner values of that array could be null though.

    You probably want to just do .pipe(map(array => array.filter(hasValue)))

    Or if you don't fancy array methods, .pipe(switchAll(), filter(hasValue), toArray()) (i.e. flattening the Observable<Array<T>> to Observable<T>, filtering, then recreating the array with the values filtered.