diff --git a/types/transducers-js/index.d.ts b/types/transducers-js/index.d.ts index cfed8fbbbe..96fce6f671 100644 --- a/types/transducers-js/index.d.ts +++ b/types/transducers-js/index.d.ts @@ -1,19 +1,9 @@ // Type definitions for transducers-js 0.4 // Project: https://github.com/cognitect-labs/transducers-js // Definitions by: Colin Kahn +// David Philipson // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -export interface IteratorResult { - done: boolean; - value?: T; -} - -export interface Iterator { - next(value?: any): IteratorResult; - return?(value?: any): IteratorResult; - throw?(e?: any): IteratorResult; -} - export interface Reduced { ['@@transducer/reduced']: boolean; ['@@transducer/value']: TResult; @@ -21,7 +11,12 @@ export interface Reduced { export type Reducer = (result: TResult, input: TInput) => TResult; -export type Transducer = (xf: Transformer) => Transformer; +// Common case: Transducer = +// Transformer => Transformer. +export type Transducer = + ( + xf: CompletingTransformer + ) => CompletingTransformer; export interface CompletingTransformer { ['@@transducer/init'](): TResult | void; @@ -44,12 +39,15 @@ export function isReduced(x: any): boolean; /** * Function composition. Take N function and return their composition. */ -export function comp(...args: T[]): T; +// Infers correct return type when all arguments have same type. +export function comp any>(...args: T[]): T; +// Falls back to (any => any) when argument types differ. +export function comp(...args: Array<(x: any) => any>): (x: any) => any; /** * Take a predicate function and return its complement. */ -export function complement(f: Function): Function; +export function complement(f: (x: T) => boolean): (x: T) => boolean; /** * Identity function. @@ -66,7 +64,7 @@ export class Map implements Transformer(f: (x: TInput) => TOutput): Transducer; +export function map(f: (x: TInput) => TOutput): Transducer; export class Filter implements Transformer { constructor(pred: (x: TInput) => boolean, xf: Transformer); @@ -78,13 +76,13 @@ export class Filter implements Transformer { /** * Filtering transducer constructor */ -export function filter(pred: (x: TInput) => boolean): Transducer; +export function filter(pred: (x: TInput) => boolean): Transducer; /** * Similar to filter except the predicate is used to * eliminate values. */ -export function remove(pred: (x: TInput) => boolean): Transducer; +export function remove(pred: (x: TInput) => boolean): Transducer; export class Keep implements Transformer { constructor(f: (x: TInput) => any, xf: Transformer); @@ -97,7 +95,7 @@ export class Keep implements Transformer { * A keeping transducer. Keep inputs as long as the provided * function does not return null or undefined. */ -export function keep(f: (x: TInput) => any): Transducer; +export function keep(f: (x: TInput) => any): Transducer; export class KeepIndexed implements Transformer { constructor(f: (i: number, x: TInput) => any, xf: Transformer); @@ -110,7 +108,7 @@ export class KeepIndexed implements Transformer(f: (i: number, x: TInput) => any): Transducer; +export function keepIndexed(f: (i: number, x: TInput) => any): Transducer; export class Take implements Transformer { constructor(n: number, xf: Transformer); @@ -123,7 +121,7 @@ export class Take implements Transformer { * A take transducer constructor. Will take n values before * returning a reduced result. */ -export function take(n: number): Transducer; +export function take(n: number): Transducer; export class TakeWhile implements Transformer { constructor(pred: (n: TInput) => boolean, xf: Transformer); @@ -136,7 +134,7 @@ export class TakeWhile implements Transformer * Like the take transducer except takes as long as the pred * return true for inputs. */ -export function takeWhile(pred: (n: TInput) => boolean): Transducer; +export function takeWhile(pred: (n: TInput) => boolean): Transducer; export class TakeNth implements Transformer { constructor(n: number, xf: Transformer); @@ -148,7 +146,7 @@ export class TakeNth implements Transformer { /** * A transducer that takes every Nth input */ -export function takeNth(n: number): Transducer; +export function takeNth(n: number): Transducer; export class Drop implements Transformer { constructor(n: number, xf: Transformer); @@ -160,7 +158,7 @@ export class Drop implements Transformer { /** * A dropping transducer constructor */ -export function drop(n: number): Transducer; +export function drop(n: number): Transducer; export class DropWhile implements Transformer { constructor(pred: (input: TInput) => boolean, xf: Transformer); @@ -173,7 +171,7 @@ export class DropWhile implements Transformer * A dropping transducer that drop inputs as long as * pred is true. */ -export function dropWhile(pred: (input: TInput) => boolean): Transducer; +export function dropWhile(pred: (input: TInput) => boolean): Transducer; export class PartitionBy implements Transformer { constructor(f: (input: TInput) => any, xf: Transformer); @@ -187,7 +185,7 @@ export class PartitionBy implements Transformer(f: (input: TInput) => any): Transducer; +export function partitionBy(f: (input: TInput) => any): Transducer; export class PartitionAll implements Transformer { constructor(n: number, xf: Transformer); @@ -200,7 +198,7 @@ export class PartitionAll implements Transformer(n: number): Transducer; +export function partitionAll(n: number): Transducer; export class Completing implements CompletingTransformer { constructor(cf: (result: TResult) => TCompleteResult, xf: Transformer); @@ -213,10 +211,12 @@ export class Completing implements CompletingT * A completing transducer constructor. Useful to provide cleanup * logic at the end of a reduction/transduction. */ -export function completing(cf: (result: TResult) => TCompleteResult): CompletingTransformer; +export function completing( + xf: Transformer | Reducer, + cf: (result: TResult) => TCompleteResult): CompletingTransformer; export class Wrap implements Transformer { - constructor(stepFn: Reducer, xf: Transformer); + constructor(stepFn: Reducer); ['@@transducer/init'](): TResult; ['@@transducer/step'](result: TResult, input: TInput): TResult; ['@@transducer/result'](result: TResult): TResult; @@ -227,44 +227,102 @@ export class Wrap implements Transformer { * accumluation and the second argument is the next input and convert * it into a transducer transformer object. */ -export function wrap(stepFn: Reducer): Transducer; +export function wrap(stepFn: Reducer): Transformer; /** * Given a transformer return a concatenating transformer */ -export function cat(xf: Transformer): Transformer ; +export function cat(xf: Transformer): Transformer>; /** * A mapping concatenating transformer */ -export function mapcat(f: (arr: TInput[]) => TOutput[]): Transducer; +export function mapcat(f: (arr: TInput) => Iterable): Transducer; /** * Given a transducer, a builder function, an initial value * and a iterable collection - returns the reduction. */ export function transduce( - xf: Transducer, - f: Transformer | Reducer, + xf: Transducer, + f: Reducer, init: TResult, - coll: TInput[] | Iterator | string | Object): TResult; + coll: Iterable): TResult; +export function transduce( + xf: Transducer, + f: CompletingTransformer, + init: TResult, + coll: Iterable): TCompleteResult; +export function transduce( + xf: Transducer, + f: CompletingTransformer, + coll: Iterable): TCompleteResult; +// Overloads for object iteration. +export function transduce( + xf: Transducer<[string, TInput], TOutput>, + f: Reducer, + init: TResult, + coll: { [key: string]: TInput }): TResult; +export function transduce( + xf: Transducer<[string, TInput], TOutput>, + f: CompletingTransformer, + init: TResult, + coll: { [key: string]: TInput }): TCompleteResult; +export function transduce( + xf: Transducer<[string, TInput], TOutput>, + f: CompletingTransformer, + coll: { [key: string]: TInput }): TCompleteResult; /** * Given a transducer, an intial value and a * collection - returns the reduction. */ -export function reduce( - xf: Transducer, +export function reduce( + xf: Transformer | Reducer, init: TResult, - coll: TInput[] | Iterator | string | Object): TResult; + coll: Iterable): TResult; +export function reduce( + xf: CompletingTransformer, + init: TResult, + coll: Iterable): TCompleteResult; +// Overloads for object iteration. +export function reduce( + xf: Transformer | Reducer, + init: TResult, + coll: { [key: string]: TInput }): TResult; +export function reduce( + xf: CompletingTransformer, + init: TResult, + coll: { [key: string]: TInput }): TCompleteResult; /** * Reduce a value into the given empty value using a transducer. */ -export function into( - empty: TResult, - xf: Transducer, - coll: TInput[] | Iterator | string | Object): TResult; +export function into( + empty: TOutput[], + xf: Transducer, + coll: Iterable): TOutput[]; +export function into( + empty: string, + xf: Transducer, + coll: Iterable): string; +export function into( + empty: { [key: string]: TOutput }, + xf: Transducer, + coll: Iterable): { [key: string]: TOutput }; +// Overloads for object iteration. +export function into( + empty: TOutput[], + xf: Transducer<[string, TInput], TOutput>, + coll: { [key: string]: TInput }): TOutput[]; +export function into( + empty: string, + xf: Transducer<[string, TInput], string>, + coll: { [key: string]: TInput }): string; +export function into( + empty: { [key: string]: TOutput }, + xf: Transducer<[string, TInput], [string, TOutput]>, + coll: { [key: string]: TInput }): { [key: string]: TOutput }; /** * Convert a transducer transformer object into a function so @@ -272,9 +330,9 @@ export function into( * Underscore, lodash */ export function toFn( - xf: Transducer, - builder: Reducer | Transformer -): Reducer; + xf: Transducer, + builder: Reducer | Transformer +): Reducer; /** * A transformer which simply returns the first input. diff --git a/types/transducers-js/transducers-js-tests.ts b/types/transducers-js/transducers-js-tests.ts index 634309a2b5..7a82b595c8 100644 --- a/types/transducers-js/transducers-js-tests.ts +++ b/types/transducers-js/transducers-js-tests.ts @@ -124,3 +124,59 @@ function mapcatExample() { const xf = t.mapcat(reverse); t.into([], xf, [[3, 2, 1], [6, 5, 4]]); // [1, 2, 3, 4, 5, 6] } + +// Original tests + +function transduceExample() { + const { completing, transduce, wrap } = t; + const stringAppendFn = (acc: string, x: number) => acc + x; + const stringAppendTransformer = wrap(stringAppendFn); + const stringAppendThenLengthTransformer = completing( + stringAppendFn, + s => s.length, + ); + const lengthsString1: string = transduce( + t.map((s: string) => s.length), + stringAppendFn, + "", + ["a", "b"], + ); + const lengthsString2: string = transduce( + t.map((s: string) => s.length), + stringAppendTransformer, + "", + ["a", "b"], + ); + const lengthsStringLength: number = transduce( + t.map((s: string) => s.length), + stringAppendThenLengthTransformer, + "", + ["a", "b"], + ); +} + +function advancedIntoExample() { + const array: number[] = into([], t.map((s: string) => s.length), [ + "a", + "b", + ]); + const string: string = into("", t.map((s: string) => s + s), ["a", "b"]); + const object1: { [key: string]: number } = into( + {}, + t.map((s: string) => [s, s.length]), + ["a", "b"], + ); + const object2: { [key: string]: boolean } = into( + {}, + t.map((kv: [string, number]) => [kv[0], true]), + { a: 1, b: 2 } + ); +} + +function compExample() { + const fn1: t.Transducer = comp(map(inc), filter(isEven)); + const fn2: t.Transducer = comp( + filter(isEven), + map((x: number) => "" + x), + ); +}