Skip to content

Commit

Permalink
fix(curry): improve types of curried operators
Browse files Browse the repository at this point in the history
type info gets missed
  • Loading branch information
tusharmath committed Nov 15, 2016
1 parent 75f94ea commit a2aff43
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 118 deletions.
16 changes: 1 addition & 15 deletions src/lib/Curry.ts
Expand Up @@ -3,25 +3,11 @@
*/


import {
ICurriedFunction,
ICurriedFunction2,
ICurriedFunction3
} from '../types/ICurriedFunction'

export function Curry (f: ICurriedFunction): ICurriedFunction {
export function Curry (f: Function): Function {
if (f.length <= 1) return f
return function curried (...t: any[]) {
if (t.length === 0) return curried
if (t.length >= f.length) return f(...t)
return curried.bind(this, ...t)
}
}

export function Curry2<T1, T2, R> (f: {(t1: T1, t2: T2): R}) {
return Curry(f) as ICurriedFunction2<T1, T2, R>
}

export function Curry3<T1, T2, T3, R> (f: {(t1: T1, t2: T2, t3: T3): R}) {
return Curry(f) as ICurriedFunction3<T1, T2, T3, R>
}
14 changes: 10 additions & 4 deletions src/lib/ForEach.ts
Expand Up @@ -5,10 +5,16 @@
import {IObservable} from '../types/core/IObservable'
import {DefaultScheduler} from '../scheduling/DefaultScheduler'
import {ISubscription} from '../types/core/ISubscription'
import {Curry2} from './Curry'
import {ICurriedFunction2} from '../types/ICurriedFunction'
import {Curry} from './Curry'
import {Observer} from './Observer'

export const forEach = Curry2(function <T> (onNext: {(value: T): void}, observable: IObservable<any>) {
export type TOnNext<T> = {(value: T): void}
export type TSource<T> = IObservable<T>
export type TResult = ISubscription

export const forEach = Curry(function <T> (onNext: TOnNext<T>, observable: TSource<T>) {
return observable.subscribe(Observer.of(onNext), DefaultScheduler.of())
}) as ICurriedFunction2<{(value: any): void}, IObservable<any>, ISubscription>
}) as Function &
{<T, R> (onNext: TOnNext<T>, source: TSource<T>): TResult} &
{<T, R> (onNext: TOnNext<T>): {(source: TSource<T>): TResult}}

14 changes: 9 additions & 5 deletions src/operators/Filter.ts
Expand Up @@ -7,9 +7,11 @@ import {IObservable} from '../types/core/IObservable'
import {IObserver} from '../types/core/IObserver'
import {ISubscription} from '../types/core/ISubscription'
import {IScheduler} from '../types/IScheduler'
import {Curry2} from '../lib/Curry'
import {ICurriedFunction2} from '../types/ICurriedFunction'
import {Curry} from '../lib/Curry'

export type TPredicate<T> = {(value: T): boolean}
export type TSource<T> = IObservable<T>
export type TResult<T> = IObservable<T>

class FilterObserver <T> implements IObserver<T> {
constructor (private predicate: {(t: T): boolean}, private sink: IObserver<T>) {
Expand All @@ -29,7 +31,7 @@ class FilterObserver <T> implements IObserver<T> {
}


export class FilterObservable <T> implements IObservable<T> {
export class FilterObservable <T> implements TResult<T> {
constructor (private predicate: {(t: T): boolean},
private source: IObservable<T>) {
}
Expand All @@ -39,6 +41,8 @@ export class FilterObservable <T> implements IObservable<T> {
}
}

export const filter = Curry2(function (predicate: {(t: any): boolean}, source: IObservable<any>) {
export const filter = Curry(function<T> (predicate: TPredicate<T>, source: TSource<T>) {
return new FilterObservable(predicate, source)
}) as ICurriedFunction2<{(t: any): boolean}, IObservable<any>, IObservable<any>>
}) as Function &
{<T> (predicate: TPredicate<T>, source: TSource<T>): TResult<T>} &
{<T> (predicate: TPredicate<T>): {(source: TSource<T>): TResult<T>}}
27 changes: 17 additions & 10 deletions src/operators/Map.ts
Expand Up @@ -6,11 +6,16 @@ import {IObservable} from '../types/core/IObservable'
import {IObserver} from '../types/core/IObserver'
import {ISubscription} from '../types/core/ISubscription'
import {IScheduler} from '../types/IScheduler'
import {Curry2} from '../lib/Curry'
import {ICurriedFunction2} from '../types/ICurriedFunction'
import {Curry} from '../lib/Curry'

class MapObserver<T> implements IObserver<T> {
constructor (private mapper: (a: T) => T, private sink: IObserver<T>) {

export type TMapper<T, R> = (value: T) => R
export type TSource<T> = IObservable<T>
export type TResult<R> = IObservable<R>


class MapObserver<T, R> implements IObserver<T> {
constructor (private mapper: TMapper<T, R>, private sink: IObserver<R>) {

}

Expand All @@ -27,15 +32,17 @@ class MapObserver<T> implements IObserver<T> {
}
}

export class MapObservable <T> implements IObservable<T> {
constructor (private mapper: (a: T) => T, private observer: IObservable<T>) {
export class MapObservable <T, R> implements TResult<R> {
constructor (private mapper: TMapper<T, R>, private source: TSource<T>) {
}

subscribe (observer: IObserver<T>, scheduler: IScheduler): ISubscription {
return this.observer.subscribe(new MapObserver(this.mapper, observer), scheduler)
subscribe (observer: IObserver<R>, scheduler: IScheduler): ISubscription {
return this.source.subscribe(new MapObserver(this.mapper, observer), scheduler)
}
}

export const map = Curry2(function (mapFunction: (a: any) => any, source: IObservable<any>) {
export const map = Curry(function <T, R> (mapFunction: (a: T) => R, source: IObservable<T>) {
return new MapObservable(mapFunction, source)
}) as ICurriedFunction2<(value: any) => any, IObservable<any>, IObservable<any>>
}) as Function &
{<T, R> (mapper: TMapper<T, R>, source: TSource<T>): TResult<T>} &
{<T, R> (mapper: TMapper<T, R>): {(source: TSource<T>): TResult<T>}}
1 change: 0 additions & 1 deletion src/operators/Multicast.ts
Expand Up @@ -54,7 +54,6 @@ export class Multicast<T> implements IObservable<T> {
}



subscribe (observer: IObserver<T>, scheduler: IScheduler): ISubscription {
return new MulticastSubscription(observer, scheduler, this.sharedObserver)
}
Expand Down
39 changes: 24 additions & 15 deletions src/operators/Reduce.ts
Expand Up @@ -7,13 +7,18 @@ import {IObservable} from '../types/core/IObservable'
import {IObserver} from '../types/core/IObserver'
import {ISubscription} from '../types/core/ISubscription'
import {IScheduler} from '../types/IScheduler'
import {Curry3} from '../lib/Curry'
import {ICurriedFunction3} from '../types/ICurriedFunction'
import {Curry} from '../lib/Curry'

class ReduceObserver<T> implements IObserver<T> {
constructor (private reducer: {(current: T, memory: T): T},
private value: T,
private sink: IObserver<T>) {

export type TReducer<T, R> = {(previousValue: R, currentValue: T): R}
export type TSeed<R> = R
export type TSource<T> = IObservable<T>
export type TResult<R> = IObservable<R>

class ReduceObserver<T, R> implements IObserver<T> {
constructor (private reducer: TReducer<T, R>,
private value: TSeed<R>,
private sink: IObserver<R>) {
}

next (val: T): void {
Expand All @@ -30,17 +35,21 @@ class ReduceObserver<T> implements IObserver<T> {
}
}

export class ReduceObservable <T> implements IObservable<T> {
constructor (private reducer: {(current: T, memory: T): T},
private value: T,
private source: IObservable<T>) {
export class ReduceObservable <T, R> implements TResult<R> {
constructor (private reducer: TReducer<T, R>,
private seed: TSeed<R>,
private source: TSource<T>) {
}

subscribe (obr: IObserver<T>, scheduler: IScheduler): ISubscription {
return this.source.subscribe(new ReduceObserver(this.reducer, this.value, obr), scheduler)
subscribe (obr: IObserver<R>, scheduler: IScheduler): ISubscription {
return this.source.subscribe(new ReduceObserver<T, R>(this.reducer, this.seed, obr), scheduler)
}
}

export const reduce = Curry3(function (reducer: {(current: any, memory: any): any}, value: any, source: IObservable<any>) {
return new ReduceObservable(reducer, value, source)
}) as ICurriedFunction3<{(current: any, memory: any): any}, any, IObservable<any>, IObservable<any>>
export const reduce = Curry(function <T, R> (t0: TReducer<T, R>, t1: R, t2: IObservable<T>) {
return new ReduceObservable(t0, t1, t2)
}) as Function &
{<T, R>(reducer: TReducer<T, R>, seed: TSeed<R>, source: TSource<T>): TResult<R>} &
{<T, R>(reducer: TReducer<T, R>): {(seed: TSeed<R>, source: TSource<T>): TResult<R>}} &
{<T, R>(reducer: TReducer<T, R>, seed: TSeed<R>): {(source: TSource<T>): TResult<R>}} &
{<T, R>(reducer: TReducer<T, R>): { (seed: TSeed<R>): { (source: TSource<T>): TResult<R> } } }
33 changes: 19 additions & 14 deletions src/operators/Sample.ts
Expand Up @@ -7,14 +7,15 @@ import {IObserver} from '../types/core/IObserver'
import {IScheduler} from '../types/IScheduler'
import {ISubscription} from '../types/core/ISubscription'
import {CompositeSubscription} from '../lib/CompositeSubscription'
import {Curry3} from '../lib/Curry'
import {ICurriedFunction3} from '../types/ICurriedFunction'
import {Curry} from '../lib/Curry'

enum StreamStatus { IDLE, STARTED, COMPLETED }

export interface ISampleSelector {
(...e: Array<any>): any
}
export type TSelector<T> = {(...e: Array<any>): T}
export type TSampler = IObservable<any>
export type TSources = Array<IObservable<any>>
export type TResult<T> = IObservable<T>

enum StreamStatus { IDLE, STARTED, COMPLETED }

function createArray<T> (size: number, value: T) {
const arr: Array<T> = new Array(size)
Expand Down Expand Up @@ -49,7 +50,7 @@ export class SampleObserver<T> implements IObserver<T> {
private completedCount = 0
private samplerCompleted = false

constructor (private total: number, private sink: IObserver<Array<T>>, private func: ISampleSelector) {
constructor (private total: number, private sink: IObserver<T>, private func: TSelector<T>) {
}

onNext (value: T, id: number) {
Expand Down Expand Up @@ -91,13 +92,13 @@ export class SampleObserver<T> implements IObserver<T> {
}


export class SampleObservable<T> implements IObservable<Array<T>> {
constructor (private func: ISampleSelector,
private sampler: IObservable<T>,
private sources: Array<IObservable<T>>) {
export class SampleObservable<T> implements TResult<T> {
constructor (private func: TSelector<T>,
private sampler: TSampler,
private sources: TSources) {
}

subscribe (observer: IObserver<Array<T>>, scheduler: IScheduler): ISubscription {
subscribe (observer: IObserver<T>, scheduler: IScheduler): ISubscription {
const cSub = new CompositeSubscription()
const sampleObserver = new SampleObserver(this.sources.length, observer, this.func)
cSub.add(this.sampler.subscribe(sampleObserver, scheduler))
Expand All @@ -109,6 +110,10 @@ export class SampleObservable<T> implements IObservable<Array<T>> {
}
}

export const sample = Curry3(function (f: ISampleSelector, sampler: IObservable<any>, sources: Array<IObservable<any>>) {
export const sample = Curry(function <T, R> (f: TSelector<R>, sampler: TSampler, sources: TSources) {
return new SampleObservable(f, sampler, sources)
}) as ICurriedFunction3<ISampleSelector, IObservable<any>, Array<IObservable<any>>, IObservable<any>>
}) as Function &
{<T>(selector: TSelector<T>, sampler: TSampler, source: TSources): TResult<T>} &
{<T>(selector: TSelector<T>): {(sampler: TSampler, source: TSources): TResult<T>}} &
{<T>(selector: TSelector<T>, sampler: TSampler): {(source: TSources): TResult<T>}} &
{<T>(selector: TSelector<T>): { (sampler: TSampler): { (source: TSources): TResult<T> } } }
26 changes: 16 additions & 10 deletions src/operators/Scan.ts
Expand Up @@ -7,14 +7,16 @@ import {IObservable} from '../types/core/IObservable'
import {IObserver} from '../types/core/IObserver'
import {IScheduler} from '../types/IScheduler'
import {ISubscription} from '../types/core/ISubscription'
import {Curry3} from '../lib/Curry'
import {ICurriedFunction3} from '../types/ICurriedFunction'
import {Curry} from '../lib/Curry'

export type Reducer <T, V> = (current: T, memory: V) => V
export type TReducer <T, R> = (current: T, memory: R) => R
export type TSeed <R> = R
export type TSource <T> = IObservable<T>
export type TResult <R> = IObservable<R>

export class ScanObserver<T, V> implements IObserver<T> {

constructor (private reducer: Reducer<T, V>,
constructor (private reducer: TReducer<T, V>,
private value: V,
private sink: IObserver<V>) {
}
Expand All @@ -34,16 +36,20 @@ export class ScanObserver<T, V> implements IObserver<T> {

}

export class ScanObservable<T, V> implements IObservable<V> {
constructor (private reducer: Reducer<T, V>, private value: V, private source: IObservable<T>) {
export class ScanObservable<T, R> implements TResult<R> {
constructor (private reducer: TReducer<T, R>, private seed: TSeed<R>, private source: TSource<T>) {

}

subscribe (observer: IObserver<V>, scheduler: IScheduler): ISubscription {
return this.source.subscribe(new ScanObserver<T, V>(this.reducer, this.value, observer), scheduler)
subscribe (observer: IObserver<R>, scheduler: IScheduler): ISubscription {
return this.source.subscribe(new ScanObserver<T, R>(this.reducer, this.seed, observer), scheduler)
}
}

export const scan = Curry3(function <T, V> (reducer: Reducer<T, V>, value: V, source: IObservable<T>) {
export const scan = Curry(function <T, V> (reducer: TReducer<T, V>, value: V, source: IObservable<T>) {
return new ScanObservable(reducer, value, source)
}) as ICurriedFunction3<Reducer<any, any>, any, IObservable<any>, IObservable<any>>
}) as Function &
{<T, R>(reducer: TReducer<T, R>, seed: TSeed<R>, source: TSource<T>): TResult<R>} &
{<T, R>(reducer: TReducer<T, R>): {(seed: TSeed<R>, source: TSource<T>): TResult<R>}} &
{<T, R>(reducer: TReducer<T, R>, seed: TSeed<R>): {(source: TSource<T>): TResult<R>}} &
{<T, R>(reducer: TReducer<T, R>): { (seed: TSeed<R>): { (source: TSource<T>): TResult<R> } } }
18 changes: 12 additions & 6 deletions src/operators/SkipRepeats.ts
Expand Up @@ -6,8 +6,11 @@ import {IObservable} from '../types/core/IObservable'
import {IObserver} from '../types/core/IObserver'
import {ISubscription} from '../types/core/ISubscription'
import {IScheduler} from '../types/IScheduler'
import {Curry2} from '../lib/Curry'
import {ICurriedFunction2} from '../types/ICurriedFunction'
import {Curry} from '../lib/Curry'

export type THasher<T, R> = (value: T) => R
export type TSource<T> = IObservable<T>
export type TResult<T> = IObservable<T>

class SkipRepeatsObserver <T, H> implements IObserver<T> {
private hash: H | void = undefined
Expand Down Expand Up @@ -38,15 +41,18 @@ class SkipRepeatsObserver <T, H> implements IObserver<T> {
}
}

export class SkipRepeatsObservable <T, H> implements IObservable <T> {
constructor (private hashFunction: {(a: T): H}, private source: IObservable<T>) {
export class SkipRepeatsObservable <T, H> implements TResult <T> {
constructor (private hashFunction: THasher<T, H>, private source: TSource<T>) {
}

subscribe (observer: IObserver<T>, scheduler: IScheduler): ISubscription {
return this.source.subscribe(new SkipRepeatsObserver(this.hashFunction, observer), scheduler)
}
}

export const skipRepeats = Curry2(function (hashFunction: {(t: any): any}, source: IObservable<any>) {
export const skipRepeats = Curry(function (hashFunction: {(t: any): any}, source: IObservable<any>) {
return new SkipRepeatsObservable(hashFunction, source)
}) as ICurriedFunction2<{(t: any): any}, IObservable<any>, IObservable<any>>
}) as Function &
{<T, R> (mapper: THasher<T, R>, source: TSource<T>): TResult<T>} &
{<T, R> (mapper: THasher<T, R>): {(source: TSource<T>): TResult<T>}}

11 changes: 7 additions & 4 deletions src/operators/Slice.ts
Expand Up @@ -6,8 +6,7 @@ import {IObservable} from '../types/core/IObservable'
import {IObserver} from '../types/core/IObserver'
import {ISubscription} from '../types/core/ISubscription'
import {IScheduler} from '../types/IScheduler'
import {Curry3} from '../lib/Curry'
import {ICurriedFunction3} from '../types/ICurriedFunction'
import {Curry} from '../lib/Curry'

class SliceObserver<T> implements IObserver<T> {
closed: boolean
Expand Down Expand Up @@ -63,6 +62,10 @@ export class SliceObservable<T> implements IObservable<T> {

}

export const slice = Curry3(function (start: number, count: number, source: IObservable<any>) {
export const slice = Curry(function (start: number, count: number, source: IObservable<any>) {
return new SliceObservable(start, count, source)
}) as ICurriedFunction3<number, number, IObservable<any>, IObservable<any>>
}) as Function &
{<T>(start: number, count: number, source: IObservable<T>): IObservable<T>} &
{<T>(start: number): {(count: number, source: IObservable<T>): IObservable<T>}} &
{<T>(start: number, count: number): {(source: IObservable<T>): IObservable<T>}} &
{<T>(start: number): { (count: number): { (source: IObservable<T>): IObservable<T> } } }

0 comments on commit a2aff43

Please sign in to comment.