hunk.code_window:   const p = of(1, 2, 3).pipe(multicast(new Subject<number>(), p => of('foo'))); // $ExpectType Observable<string>
     const q = of(1, 2, 3).pipe(multicast(() => new Subject<number>(), p => p)); // $ExpectType Observable<number>
     const r = of(1, 2, 3).pipe(multicast(() => new Subject<number>(), p => of('foo'))); // $ExpectType Observable<string>
   });
   it('should enforce types', () => {
     const p = of(1, 2, 3).pipe(multicast()); // $ExpectError
   });
  
hunk.labels: keep keep keep keep add keep keep keep
hunk.after_edit: it('should support union types', () => {
     const o = of(1, 2, 3).pipe(multicast(new Subject<number>(), p => Math.random() > 0.5 ? of(123) : of('foo'))); // $ExpectType Observable<string | number>
     const p = of(1, 2, 3).pipe(multicast(() => new Subject<number>(), p => Math.random() > 0.5 ? of(123) : of('foo'))); // $ExpectType Observable<string | number>
   });
  
hunk.file_path: spec-dtslint/operators/multicast-spec.ts
hunk.type: add
file: import { expect } from 'chai';
  import { of, Observable } from 'rxjs';
  import { concat, mergeMap } from 'rxjs/operators';
  import { TestScheduler } from 'rxjs/testing';
  import { hot, cold, expectObservable, expectSubscriptions } from '../helpers/marble-testing';
  
  declare function asDiagram(arg: string): Function;
  
  declare const rxTestScheduler: TestScheduler;
  
  /** @test {concat} */
  describe('concat operator', () => {
    asDiagram('concat')('should concatenate two cold observables', () => {
      const e1 =   cold('--a--b-|');
      const e2 =   cold(       '--x---y--|');
      const expected =  '--a--b---x---y--|';
  
      expectObservable(e1.pipe(concat(e2, rxTestScheduler))).toBe(expected);
    });
  
    it('should work properly with scalar observables', (done) => {
      const results: string[] = [];
  
      const s1 = new Observable<number>((observer) => {
          setTimeout(() => {
            observer.next(1);
            observer.complete();
          });
        })
        .pipe(concat(of(2)));
  
      s1.subscribe((x) => {
            results.push('Next: ' + x);
          }, (x) => {
            done(new Error('should not be called'));
          }, () => {
            results.push('Completed');
            expect(results).to.deep.equal(['Next: 1', 'Next: 2', 'Completed']);
            done();
          }
        );
    });
  
    it('should complete without emit if both sources are empty', () => {
      const e1 =   cold('--|');
      const e1subs =    '^ !';
      const e2 =   cold(  '----|');
      const e2subs =    '  ^   !';
      const expected =  '------|';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should not complete if first source does not completes', () => {
      const e1 =   cold('-');
      const e1subs =    '^';
      const e2 =   cold('--|');
      const e2subs: string[] = [];
      const expected =  '-';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should not complete if second source does not completes', () => {
      const e1 =   cold('--|');
      const e1subs =    '^ !';
      const e2 =   cold('---');
      const e2subs =    '  ^';
      const expected =  '---';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should not complete if both sources do not complete', () => {
      const e1 =   cold('-');
      const e1subs =    '^';
      const e2 =   cold('-');
      const e2subs: string[] = [];
      const expected =  '-';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should raise error when first source is empty, second source raises error', () => {
      const e1 =   cold('--|');
      const e1subs =    '^ !';
      const e2 =   cold(  '----#');
      const e2subs =    '  ^   !';
      const expected =  '------#';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should raise error when first source raises error, second source is empty', () => {
      const e1 =   cold('---#');
      const e1subs =    '^  !';
      const e2 =   cold('----|');
      const e2subs: string[] = [];
      const expected =  '---#';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should raise first error when both source raise error', () => {
      const e1 =   cold('---#');
      const e1subs =    '^  !';
      const e2 =   cold('------#');
      const e2subs: string[] = [];
      const expected =  '---#';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should concat if first source emits once, second source is empty', () => {
      const e1 =   cold('--a--|');
      const e1subs =    '^    !';
      const e2 =   cold(     '--------|');
      const e2subs =    '     ^       !';
      const expected =  '--a----------|';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should concat if first source is empty, second source emits once', () => {
      const e1 =   cold('--|');
      const e1subs =    '^ !';
      const e2 =   cold(  '--a--|');
      const e2subs =    '  ^    !';
      const expected =  '----a--|';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should emit element from first source, and should not complete if second ' +
    'source does not completes', () => {
      const e1 =   cold('--a--|');
      const e1subs =    '^    !';
      const e2 =   cold(     '-');
      const e2subs =    '     ^';
      const expected =  '--a---';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should not complete if first source does not complete', () => {
      const e1 =   cold('-');
      const e1subs =    '^';
      const e2 =   cold('--a--|');
      const e2subs: string[] = [];
      const expected =  '-';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should emit elements from each source when source emit once', () => {
      const e1 =   cold('---a|');
      const e1subs =    '^   !';
      const e2 =   cold(    '-----b--|');
      const e2subs =    '    ^       !';
      const expected =  '---a-----b--|';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should unsubscribe to inner source if outer is unsubscribed early', () => {
      const e1 =   cold('---a-a--a|            ');
      const e1subs =    '^        !            ';
      const e2 =   cold(         '-----b-b--b-|');
      const e2subs =    '         ^       !    ';
      const unsub =     '                 !    ';
      const expected =  '---a-a--a-----b-b     ';
  
      expectObservable(e1.pipe(concat(e2)), unsub).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should not break unsubscription chains when result is unsubscribed explicitly', () => {
      const e1 =   cold('---a-a--a|            ');
      const e1subs =    '^        !            ';
      const e2 =   cold(         '-----b-b--b-|');
      const e2subs =    '         ^       !    ';
      const expected =  '---a-a--a-----b-b-    ';
      const unsub =     '                 !    ';
  
      const result = e1.pipe(
        mergeMap((x) => of(x)),
        concat(e2),
        mergeMap((x) => of(x))
      );
  
      expectObservable(result, unsub).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should raise error from first source and does not emit from second source', () => {
      const e1 =   cold('--#');
      const e1subs =    '^ !';
      const e2 =   cold('----a--|');
      const e2subs: string[] = [];
      const expected =  '--#';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should emit element from first source then raise error from second source', () => {
      const e1 =   cold('--a--|');
      const e1subs =    '^    !';
      const e2 =   cold(     '-------#');
      const e2subs =    '     ^      !';
      const expected =  '--a---------#';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should emit all elements from both hot observable sources if first source ' +
    'completes before second source starts emit', () => {
      const e1 =   hot('--a--b-|');
      const e1subs =   '^      !';
      const e2 =   hot('--------x--y--|');
      const e2subs =   '       ^      !';
      const expected = '--a--b--x--y--|';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should emit elements from second source regardless of completion time ' +
    'when second source is cold observable', () => {
      const e1 =   hot('--a--b--c---|');
      const e1subs =   '^           !';
      const e2 =  cold('-x-y-z-|');
      const e2subs =   '            ^      !';
      const expected = '--a--b--c----x-y-z-|';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should not emit collapsing element from second source', () => {
      const e1 =   hot('--a--b--c--|');
      const e1subs =   '^          !';
      const e2 =   hot('--------x--y--z--|');
      const e2subs =   '           ^     !';
      const expected = '--a--b--c--y--z--|';
  
      expectObservable(e1.pipe(concat(e2))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
    });
  
    it('should accept scheduler with multiple observables', () => {
      const e1 =   cold('---a|');
      const e1subs =    '^   !';
      const e2 =   cold(    '---b--|');
      const e2subs =    '    ^     !';
      const e3 =   cold(          '---c--|');
      const e3subs =    '          ^     !';
      const expected =  '---a---b-----c--|';
  
      expectObservable(e1.pipe(concat(e2, e3, rxTestScheduler))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
      expectSubscriptions(e2.subscriptions).toBe(e2subs);
      expectSubscriptions(e3.subscriptions).toBe(e3subs);
    });
  
    it('should accept scheduler without observable parameters', () => {
      const e1 =   cold('---a-|');
      const e1subs =    '^    !';
      const expected =  '---a-|';
  
      expectObservable(e1.pipe(concat(rxTestScheduler))).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
    });
  
    it('should emit self without parameters', () => {
      const e1 =   cold('---a-|');
      const e1subs =    '^    !';
      const expected =  '---a-|';
  
      expectObservable(e1.pipe(concat())).toBe(expected);
      expectSubscriptions(e1.subscriptions).toBe(e1subs);
    });
  });
  