<commit_before>import { Operator } from '../Operator';
import { Observable } from '../Observable';
import { Subscriber } from '../Subscriber';
import { async } from '../scheduler/async';
import { OperatorFunction, SchedulerLike, TimeInterval as TimeIntervalInterface } from '../types';

export function timeInterval<T>(scheduler: SchedulerLike = async): OperatorFunction<T, TimeInterval<T>> {
  return (source: Observable<T>) => source.lift(new TimeIntervalOperator(scheduler));
}

export class TimeInterval<T> implements TimeIntervalInterface<T> {
  constructor(public value: T, public interval: number) {

  }
}

class TimeIntervalOperator<T> implements Operator<T, TimeInterval<T>> {
  constructor(private scheduler: SchedulerLike) {

  }

  call(observer: Subscriber<TimeInterval<T>>, source: any): any {
    return source.subscribe(new TimeIntervalSubscriber(observer, this.scheduler));
  }
}

/**
 * We need this JSDoc comment for affecting ESDoc.
 * @ignore
 * @extends {Ignored}
 */
class TimeIntervalSubscriber<T> extends Subscriber<T> {
  private lastTime: number = 0;

  constructor(destination: Subscriber<TimeInterval<T>>, private scheduler: SchedulerLike) {
    super(destination);

    this.lastTime = scheduler.now();
  }

  protected _next(value: T) {
    let now = this.scheduler.now();
    let span = now - this.lastTime;
    this.lastTime = now;

    this.destination.next(new TimeInterval(value, span));
  }
}
<commit_msg>refactor(timeInterval): implement in terms of scan<commit_after>
import { Observable } from '../Observable';
import { async } from '../scheduler/async';
import { SchedulerLike, OperatorFunction } from '../types';
import { scan } from './scan';
import { defer } from '../observable/defer';
import { map } from './map';

export function timeInterval<T>(scheduler: SchedulerLike = async): OperatorFunction<T, TimeInterval<T>> {
  return (source: Observable<T>) => defer(() => {
    return source.pipe(
      // HACK: the typings seem off with scan
      scan(
        ({ current }, value) => ({ value, current: scheduler.now(), last: current }),
        { current: scheduler.now(), value: undefined,  last: undefined }
      ) as any,
      map<any, TimeInterval<T>>(({ current, last, value }) => new TimeInterval(value, current - last)),
    );
  });
}

export class TimeInterval<T> {
  constructor(public value: T, public interval: number) {}
}

{'fraction_non_alphanumeric': 0.1436950146627566, 'fraction_numerical': 0.00041893590280687055, 'mean_word_length': 4.342281879194631, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6525613', 'n_tokens_mistral': 698, 'n_tokens_neox': 679, 'n_words': 191}