Search code examples
javascriptangulartypescriptrxjsngrx

Combining multiple pipeable NgRx selectors


Is it possible to combine multiple pipeable selectors the same way we can combine multiple regular selectors?

Combining regular selectors:

export const selectActiveOrganization = createSelector(
    selectOrganizations,
    selectActiveOrganizationId,
    (organizations, activeOrgId) => organizations[activeOrgId],
);

Above there are two selectors selectOrganizations and selectActiveOrganizationId, which are passed into createSelector to create a selectActiveOrganization.

Problem here is that selectActiveOrganization can also return undefined.


Now let's rewrite this to pipeable selector:

const _selectActiveOrganization = createSelector(
    selectOrganizations,
    selectActiveOrganizationId,
    (organizations, activeOrgId) => organizations[activeOrgId],
);

export const selectActiveOrganizationPipeable = pipe(
    select(_selectActiveOrganization),
    filter(activeOrg => !!activeOrg),
);

In selectActiveOrganizationPipeable we improved the selectActiveOrganization selector to only emit value if there is any active organization.

So far so good.

Now let's say we want to build on to of our pipeable selector and create a new one which is returning only the organization name.

export const selectActiveOrganizationNamePipeable = pipe(
    select(selectActiveOrganizationPipeable),
    map(organization => organization.name), // --> TS ERROR: Property 'name' does not exist on type 'Observable<Organization>'.ts(2339)
);

Is there a way to reuse existing selectActiveOrganizationPipeable? (similarly as we reuse regular selectors)


Solution

  • Something like this should work. You can use the previous pipe within the new pipe.

    export const selectActiveOrganizationNamePipeable = 
      pipe(
        selectActiveOrganizationPipeable,
        map(organization => organization.name)
      );