Angular2/4 broadcast service using RxJS
First of all, I recommend you to ensure your code is correct (see my comment on your question).

Here are a few suggestions about improving your code.


Please do not use non-informative names like w, ww, sep, kArg, cW, CK, and even the "well-known" i, j, k, m, n. They are absolutely horrible. They make decent code be an unreadable puzzle. They hide the intent and make me think where I should not be.
Please always make sure you use Type when a) the compiler loses (or is unable to infer) the type information; b) you can narrow down the type. That includes the function return type. Typing is not panacea but it helps prevent an entire class of bugs.
Do not use generic methods smth&lt;T&gt;(...) unless you use the type T information anywhere in the function.
Minimize the distance between variable declaration, assignment, and first usage. Better declare and assign in the same place. Ideally, find a way to not even declare a variable.
In error messages be more specific about what went wrong.




  const star = '*';
  const twoStars = '**';

  export class RadioService {
    private separator = ':';
    private _eventBus = new Subject&lt;RadioEvent&gt;();
    private _eventCacheBus = new ReplaySubject&lt;RadioEvent&gt;();

    keyMatch(keyList: string, wildcardList: string): boolean {
      const isMatch = (wildcard, key) =&gt; (wildcard === star) || (wildcard === key);

      const allKeys = keyList.split(this.separator);
      const allWildcards = wildcardList.split(this.separator);

      const keyWildcardPairs = allKeys
        .reduce((accum, current, index) =&gt; {
          accum.push([current, allWildcards[index]]);
          return accum;
        }, &lt;string[][]&gt;[]);

      return keyWildcardPairs.some(pair =&gt; {
        const key = pair[0];
        const wildcard = pair[1];
        // '**' match all gragments
        if (wildcard == twoStars &amp;&amp; (typeof key !== 'undefined')) {
          return true;
        }
        // test if fragments match
        if (!isMatch(wildcard, key)) {
          return true;
        }
        return false;
      });
    };

    cast(key: string, data?: any): void {
      if (typeof key !== 'string' || key.length &lt;= 0) {
        throw `Bad key '${JSON.stringify(key)}'. Please provide a non-empty string.`;
      }

      this._eventBus.next({ key: key, data: data });
      this._eventCacheBus.next({ key: key, data: data });
    };


    on(key: string, count?: number): Observable&lt;any&gt; {
      const _this = this;

      const normalObservable = this._eventBus
        .filter(event =&gt; _this.keyMatch(event.key, key))
        .map(event =&gt; event.data);

      const withoutReplay = _.isNil(count);
      if (withoutReplay)
        return normalObservable;

      const subject = new ReplaySubject&lt;number&gt;(count);
      this._eventCacheBus
        .filter(event =&gt; _this.keyMatch(event.key, key))
        .map(event =&gt; event.data)
        .subscribe(value =&gt; subject.next(value));

      return Observable
        .merge(normalObservable, subject)
        .distinct();
    }
  }