From da382da4cdcc6e7ab1ffc6a499f4f7f5ea7de130 Mon Sep 17 00:00:00 2001 From: Moshe Kolodny Date: Sun, 17 May 2020 16:04:54 -0400 Subject: [PATCH] feat(groupBy): Add typeguards support for groupBy (#5441) * feat(groupBy): Add typeguards support for groupBy * fix: use T for type guard value * test: add dtslint tests for groupBy type guard sig Co-authored-by: Moshe Kolodny Co-authored-by: Nicholas Jamieson --- spec-dtslint/operators/groupBy-spec.ts | 37 +++++++++++++++++++++++++- src/internal/operators/groupBy.ts | 1 + 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/spec-dtslint/operators/groupBy-spec.ts b/spec-dtslint/operators/groupBy-spec.ts index 04fc89003c..8f360a9dd4 100644 --- a/spec-dtslint/operators/groupBy-spec.ts +++ b/spec-dtslint/operators/groupBy-spec.ts @@ -1,5 +1,5 @@ import { of, Subject, GroupedObservable } from 'rxjs'; -import { groupBy } from 'rxjs/operators'; +import { groupBy, mergeMap } from 'rxjs/operators'; it('should infer correctly', () => { const o = of(1, 2, 3).pipe(groupBy(value => value.toString())); // $ExpectType Observable> @@ -47,3 +47,38 @@ it('should enforce types of subject selector', () => { const o = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, undefined, () => 'nope')); // $ExpectError const p = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, undefined, (value) => new Subject())); // $ExpectError }); + +it('should support a user-defined type guard', () => { + function isNumber(value: string | number): value is number { + return typeof value === 'number'; + } + const o = of('a', 1, 'b', 2).pipe( + groupBy(isNumber), + mergeMap((group) => { + if (group.key) { + const inferred = group; // $ExpectType GroupedObservable + return inferred; + } else { + const inferred = group; // $ExpectType GroupedObservable + return inferred; + } + }) + ); + const inferred = o; // $ExpectType Observable +}); + +it('should support an inline user-defined type guard', () => { + const o = of('a', 1, 'b', 2).pipe( + groupBy((value): value is number => typeof value === 'number'), + mergeMap((group) => { + if (group.key) { + const inferred = group; // $ExpectType GroupedObservable + return inferred; + } else { + const inferred = group; // $ExpectType GroupedObservable + return inferred; + } + }) + ); + const inferred = o; // $ExpectType Observable +}); diff --git a/src/internal/operators/groupBy.ts b/src/internal/operators/groupBy.ts index 9ad1ef981a..86fcb82b07 100644 --- a/src/internal/operators/groupBy.ts +++ b/src/internal/operators/groupBy.ts @@ -6,6 +6,7 @@ import { Subject } from '../Subject'; import { OperatorFunction } from '../types'; /* tslint:disable:max-line-length */ +export function groupBy(keySelector: (value: T) => value is K): OperatorFunction | GroupedObservable>>; export function groupBy(keySelector: (value: T) => K): OperatorFunction>; export function groupBy(keySelector: (value: T) => K, elementSelector: void, durationSelector: (grouped: GroupedObservable) => Observable): OperatorFunction>; export function groupBy(keySelector: (value: T) => K, elementSelector?: (value: T) => R, durationSelector?: (grouped: GroupedObservable) => Observable): OperatorFunction>;