From 246ddd52cff782412a25a597029099e53e1fdf43 Mon Sep 17 00:00:00 2001 From: David Philipson Date: Mon, 19 Jun 2017 12:02:45 -0700 Subject: [PATCH] Fixes to transducers-js types * Remove unnecessary type parameters * Update transduce() and reduce() to accept CompletingTransformers * Fix incorrect definition of transduce() * Fix incorrect definition of reduce() * Fix incorrect definition of completing() * Fix incorrect definition of wrap() * Fix incorrect definition of cat() * Fix overly strict definition of mapcat() * Make into() definition precise with overloads * Use es6 Iterables. * More precise typings for object iteration in reduce(), transduce(), and into() --- types/transducers-js/index.d.ts | 128 +++++++++++++------ types/transducers-js/transducers-js-tests.ts | 48 +++++++ 2 files changed, 137 insertions(+), 39 deletions(-) diff --git a/types/transducers-js/index.d.ts b/types/transducers-js/index.d.ts index cfed8fbbbe..3d9c6f7719 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,7 @@ export interface Reduced { export type Reducer = (result: TResult, input: TInput) => TResult; -export type Transducer = (xf: Transformer) => Transformer; +export type Transducer = (xf: Transformer) => Transformer; export interface CompletingTransformer { ['@@transducer/init'](): TResult | void; @@ -66,7 +56,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 +68,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 +87,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 +100,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 +113,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 +126,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 +138,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 +150,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 +163,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 +177,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 +190,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,7 +203,9 @@ 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); @@ -227,44 +219,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,7 +322,7 @@ export function into( * Underscore, lodash */ export function toFn( - xf: Transducer, + xf: Transducer, builder: Reducer | Transformer ): Reducer; diff --git a/types/transducers-js/transducers-js-tests.ts b/types/transducers-js/transducers-js-tests.ts index 634309a2b5..f39bf87384 100644 --- a/types/transducers-js/transducers-js-tests.ts +++ b/types/transducers-js/transducers-js-tests.ts @@ -124,3 +124,51 @@ 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 } + ); +}