From 80dd267cc2b5bc092cc45f9781e5a32134f915bd Mon Sep 17 00:00:00 2001 From: "T.J. Lawrence" Date: Sun, 19 Jan 2014 23:48:11 -0700 Subject: [PATCH 1/2] Fixed some typings with the chain syntax --- underscore/underscore-tests.ts | 36 ++++++++++++++------------ underscore/underscore.d.ts | 47 ++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/underscore/underscore-tests.ts b/underscore/underscore-tests.ts index ae5ab6f7e..ae641fde5 100644 --- a/underscore/underscore-tests.ts +++ b/underscore/underscore-tests.ts @@ -283,24 +283,28 @@ _(['test', 'test']).pick(['test2', 'test2']); //////////////// Chain Tests function chain_tests() { // https://typescript.codeplex.com/workitem/1960 - var list:number[] = _.chain([1, 2, 3, 4, 5, 6, 7, 8]) - .filter(n => n % 2 == 0) - .map(n => n * n) - .value(); - - _([1, 2, 3, 4]) - .chain() - .filter((num: number) => { - return num % 2 == 0; - }).tap(alert) - .map((num: number) => { - return num * num; - }) + var numArray: number[] = _.chain([1, 2, 3, 4, 5, 6, 7, 8]) + .filter(num => num % 2 == 0) + .map(num => num * num) .value(); - _.chain([1, 2, 3, 200]) - .filter(function (num: number) { return num % 2 == 0; }) + var strArray: string[] = _([1, 2, 3, 4]) + .chain() + .filter(num => num % 2 == 0) .tap(alert) - .map(function (num: number) { return num * num }) + .map(num => "string" + num) + .value(); + + var n : number = _.chain([1, 2, 3, 200]) + .filter(num => num % 2 == 0) + .tap(alert) + .map(num => num * num) + .max() + .value(); + + var t2 : number = _([1, 2, 3]).chain() + .map(num=> [num, num + 1]) + .flatten() + .find(num => num % 2 == 0) .value(); } diff --git a/underscore/underscore.d.ts b/underscore/underscore.d.ts index 4382f7bea..53bbdffa4 100644 --- a/underscore/underscore.d.ts +++ b/underscore/underscore.d.ts @@ -1364,7 +1364,8 @@ interface UnderscoreStatic { * @param obj Object to chain. * @return Wrapped `obj`. **/ - chain(obj: any): _Chain; + chain(obj: T[]): _Chain; + chain(obj: T): _Chain; /** * Extracts the value of a wrapped object. @@ -2194,13 +2195,25 @@ interface _Chain { * Wrapped type `any[]`. * @see _.map **/ - map(iterator: _.ListIterator, context?: any): _Chain; + map(iterator: (value: T, index: number, list: T[]) => TArray[], context?: any): _ChainOfArrays; + //Not sure why this won't work, might be a TypeScript error? map(iterator: _.ListIterator, context?: any): _ChainOfArrays; + /** + * Wrapped type `any[]`. + * @see _.map + **/ + map(iterator: _.ListIterator, context?: any): _Chain; /** * Wrapped type `any[]`. * @see _.map **/ - map(iterator: _.ObjectIterator, context?: any): _Chain; + map(iterator: (element: T, key: string, list: any) => TArray[], context?: any): _ChainOfArrays; + //Not sure why this won't work, might be a TypeScript error? //map(iterator: _.ObjectIterator, context?: any): _ChainOfArrays; + /** + * Wrapped type `any[]`. + * @see _.map + **/ + map(iterator: _.ObjectIterator, context?: any): _Chain; /** * @see _.map @@ -2243,7 +2256,7 @@ interface _Chain { * Wrapped type `any[]`. * @see _.find **/ - find(iterator: _.ListIterator, context?: any): _Chain; + find(iterator: _.ListIterator, context?: any): _ChainSingle; /** * @see _.find @@ -2271,7 +2284,7 @@ interface _Chain { * Wrapped type `any[]`. * @see _.findWhere **/ - findWhere(properties: U): _Chain; + findWhere(properties: U): _ChainSingle; /** * Wrapped type `any[]`. @@ -2323,43 +2336,43 @@ interface _Chain { * Wrapped type `any[]`. * @see _.pluck **/ - pluck(propertyName: string): _Chain; + pluck(propertyName: string): _Chain; /** * Wrapped type `number[]`. * @see _.max **/ - max(): _Chain; + max(): _ChainSingle; /** * Wrapped type `any[]`. * @see _.max **/ - max(iterator: _.ListIterator, context?: any): _Chain; + max(iterator: _.ListIterator, context?: any): _ChainSingle; /** * Wrapped type `any[]`. * @see _.max **/ - max(iterator?: _.ListIterator, context?: any): _Chain; + max(iterator?: _.ListIterator, context?: any): _ChainSingle; /** * Wrapped type `number[]`. * @see _.min **/ - min(): _Chain; + min(): _ChainSingle; /** * Wrapped type `any[]`. * @see _.min **/ - min(iterator: _.ListIterator, context?: any): _Chain; + min(iterator: _.ListIterator, context?: any): _ChainSingle; /** * Wrapped type `any[]`. * @see _.min **/ - min(iterator?: _.ListIterator, context?: any): _Chain; + min(iterator?: _.ListIterator, context?: any): _ChainSingle; /** * Wrapped type `any[]`. @@ -2518,7 +2531,7 @@ interface _Chain { * Wrapped type `any`. * @see _.flatten **/ - flatten(shallow?: boolean): _Chain; + flatten(shallow?: boolean): _Chain; /** * Wrapped type `any[]`. @@ -2947,7 +2960,13 @@ interface _Chain { * Wrapped type `any`. * @see _.value **/ - value(): TResult; + value(): T[]; +} +interface _ChainSingle { + value(): T; +} +interface _ChainOfArrays extends _Chain { + flatten(): _Chain; } declare var _: UnderscoreStatic; From 7172a17c261d11398945bd94fd53923266f6fd02 Mon Sep 17 00:00:00 2001 From: "T.J. Lawrence" Date: Mon, 20 Jan 2014 08:26:08 -0700 Subject: [PATCH 2/2] Underscore: Used tabs vs spaces for my additions and added explanation in test --- underscore/underscore-tests.ts | 44 +++--- underscore/underscore.d.ts | 252 +++++++++++++++++---------------- 2 files changed, 151 insertions(+), 145 deletions(-) diff --git a/underscore/underscore-tests.ts b/underscore/underscore-tests.ts index ae641fde5..7b5ee0504 100644 --- a/underscore/underscore-tests.ts +++ b/underscore/underscore-tests.ts @@ -283,28 +283,30 @@ _(['test', 'test']).pick(['test2', 'test2']); //////////////// Chain Tests function chain_tests() { // https://typescript.codeplex.com/workitem/1960 - var numArray: number[] = _.chain([1, 2, 3, 4, 5, 6, 7, 8]) - .filter(num => num % 2 == 0) - .map(num => num * num) - .value(); + var numArray: number[] = _.chain([1, 2, 3, 4, 5, 6, 7, 8]) + .filter(num => num % 2 == 0) + .map(num => num * num) + .value(); - var strArray: string[] = _([1, 2, 3, 4]) - .chain() - .filter(num => num % 2 == 0) - .tap(alert) - .map(num => "string" + num) - .value(); + var strArray: string[] = _([1, 2, 3, 4]) + .chain() + .filter(num => num % 2 == 0) + .tap(alert) + .map(num => "string" + num) + .value(); - var n : number = _.chain([1, 2, 3, 200]) - .filter(num => num % 2 == 0) - .tap(alert) - .map(num => num * num) - .max() - .value(); + var n : number = _.chain([1, 2, 3, 200]) + .filter(num => num % 2 == 0) + .tap(alert) + .map(num => num * num) + .max() + .value(); - var t2 : number = _([1, 2, 3]).chain() - .map(num=> [num, num + 1]) - .flatten() - .find(num => num % 2 == 0) - .value(); + //If using alternate definition of map (~ line 2200), .value returns any + // because.map matches _Chain as opposed to _ChainOfArrays , which breaks typing on flatten + var hoverOverValueShouldBeNumberNotAny : number = _([1, 2, 3]).chain() + .map(num=> [num, num + 1]) + .flatten() + .find(num => num % 2 == 0) + .value(); } diff --git a/underscore/underscore.d.ts b/underscore/underscore.d.ts index 53bbdffa4..121aa644e 100644 --- a/underscore/underscore.d.ts +++ b/underscore/underscore.d.ts @@ -6,66 +6,66 @@ // Definitions: https://github.com/borisyankov/DefinitelyTyped declare module _ { - /** - * underscore.js _.throttle options. - **/ - interface ThrottleSettings { + /** + * underscore.js _.throttle options. + **/ + interface ThrottleSettings { - /** - * If you'd like to disable the leading-edge call, pass this as false. - **/ - leading?: boolean; + /** + * If you'd like to disable the leading-edge call, pass this as false. + **/ + leading?: boolean; - /** - * If you'd like to disable the execution on the trailing-edge, pass false. - **/ - trailing?: boolean; - } + /** + * If you'd like to disable the execution on the trailing-edge, pass false. + **/ + trailing?: boolean; + } - /** - * underscore.js template settings, set templateSettings or pass as an argument - * to 'template()' to overide defaults. - **/ - interface TemplateSettings { - /** - * Default value is '/<%([\s\S]+?)%>/g'. - **/ - evaluate?: RegExp; + /** + * underscore.js template settings, set templateSettings or pass as an argument + * to 'template()' to overide defaults. + **/ + interface TemplateSettings { + /** + * Default value is '/<%([\s\S]+?)%>/g'. + **/ + evaluate?: RegExp; - /** - * Default value is '/<%=([\s\S]+?)%>/g'. - **/ - interpolate?: RegExp; + /** + * Default value is '/<%=([\s\S]+?)%>/g'. + **/ + interpolate?: RegExp; - /** - * Default value is '/<%-([\s\S]+?)%>/g'. - **/ - escape?: RegExp; - } + /** + * Default value is '/<%-([\s\S]+?)%>/g'. + **/ + escape?: RegExp; + } - interface ListIterator { - (value: T, index: number, list: T[]): TResult; - } + interface ListIterator { + (value: T, index: number, list: T[]): TResult; + } - interface ObjectIterator { - (element: T, key: string, list: any): TResult; - } + interface ObjectIterator { + (element: T, key: string, list: any): TResult; + } - interface MemoIterator { - (prev: TResult, curr: T, index: number, list: T[]): TResult; - } + interface MemoIterator { + (prev: TResult, curr: T, index: number, list: T[]): TResult; + } - interface Collection { } + interface Collection { } - // Common interface between Arrays and jQuery objects - interface List extends Collection { - [index: number]: T; - length: number; - } + // Common interface between Arrays and jQuery objects + interface List extends Collection { + [index: number]: T; + length: number; + } - interface Dictionary extends Collection { - [index: string]: T; - } + interface Dictionary extends Collection { + [index: string]: T; + } } interface UnderscoreStatic { @@ -74,10 +74,10 @@ interface UnderscoreStatic { * as the first parameter can be invoked through this function. * @param key First argument to Underscore object functions. **/ - (value: Array): Underscore; - (value: T): Underscore; + (value: Array): Underscore; + (value: T): Underscore; - /* ************* + /* ************* * Collections * ************* */ @@ -285,7 +285,7 @@ interface UnderscoreStatic { * @return The first element in `list` that has all `properties`. **/ findWhere( - list: _.List, + list: _.List, properties: U): T; /** @@ -299,7 +299,7 @@ interface UnderscoreStatic { **/ reject( list: _.Collection, - iterator: _.ListIterator, + iterator: _.ListIterator, context?: any): T[]; /** @@ -312,7 +312,7 @@ interface UnderscoreStatic { **/ every( list: _.Collection, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): boolean; /** @@ -320,7 +320,7 @@ interface UnderscoreStatic { **/ all( list: _.Collection, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): boolean; /** @@ -333,7 +333,7 @@ interface UnderscoreStatic { **/ any( list: _.Collection, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): boolean; /** @@ -341,7 +341,7 @@ interface UnderscoreStatic { **/ some( list: _.Collection, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): boolean; /** @@ -390,7 +390,7 @@ interface UnderscoreStatic { * @param list Finds the maximum value in this list. * @return Maximum value in `list`. **/ - max(list: _.List): number; + max(list: _.List): number; /** * Returns the maximum value in list. If iterator is passed, it will be used on each value to generate @@ -402,7 +402,7 @@ interface UnderscoreStatic { **/ max( list: _.Collection, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): T; /** @@ -410,7 +410,7 @@ interface UnderscoreStatic { * @param list Finds the minimum value in this list. * @return Minimum value in `list`. **/ - min(list: _.List): number; + min(list: _.List): number; /** * Returns the minimum value in list. If iterator is passed, it will be used on each value to generate @@ -422,7 +422,7 @@ interface UnderscoreStatic { **/ min( list: _.Collection, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): T; /** @@ -434,8 +434,8 @@ interface UnderscoreStatic { * @return A sorted copy of `list`. **/ sortBy( - list: _.List, - iterator?: _.ListIterator, + list: _.List, + iterator?: _.ListIterator, context?: any): T[]; /** @@ -443,7 +443,7 @@ interface UnderscoreStatic { * @param iterator Sort iterator for each element within `list`. **/ sortBy( - list: _.List, + list: _.List, iterator: string, context?: any): T[]; @@ -457,36 +457,36 @@ interface UnderscoreStatic { * @return An object with the group names as properties where each property contains the grouped elements from `list`. **/ groupBy( - list: _.List, - iterator?: _.ListIterator, - context?: any): _.Dictionary; + list: _.List, + iterator?: _.ListIterator, + context?: any): _.Dictionary; /** * @see _.groupBy * @param iterator Property on each object to group them by. **/ groupBy( - list: _.List, + list: _.List, iterator: string, - context?: any): _.Dictionary; + context?: any): _.Dictionary; /** * Given a `list`, and an `iterator` function that returns a key for each element in the list (or a property name), * returns an object with an index of each item. Just like _.groupBy, but for when you know your keys are unique. **/ indexBy( - list: _.List, - iterator: _.ListIterator, - context?: any): _.Dictionary; + list: _.List, + iterator: _.ListIterator, + context?: any): _.Dictionary; /** * @see _.indexBy * @param iterator Property on each object to index them by. **/ indexBy( - list: _.List, + list: _.List, iterator: string, - context?: any): _.Dictionary; + context?: any): _.Dictionary; /** * Sorts a list into groups and returns a count for the number of objects in each group. Similar @@ -499,8 +499,8 @@ interface UnderscoreStatic { **/ countBy( list: _.Collection, - iterator?: _.ListIterator, - context?: any): _.Dictionary; + iterator?: _.ListIterator, + context?: any): _.Dictionary; /** * @see _.countBy @@ -509,7 +509,7 @@ interface UnderscoreStatic { countBy( list: _.Collection, iterator: string, - context?: any): _.Dictionary; + context?: any): _.Dictionary; /** * Returns a shuffled copy of the list, using a version of the Fisher-Yates shuffle. @@ -554,38 +554,38 @@ interface UnderscoreStatic { * @param array Retrieves the first element of this array. * @return Returns the first element of `array`. **/ - first(array: _.List): T; + first(array: _.List): T; /** * @see _.first * @param n Return more than one element from `array`. **/ first( - array: _.List, + array: _.List, n: number): T[]; /** * @see _.first **/ - head(array: _.List): T; + head(array: _.List): T; /** * @see _.first **/ head( - array: _.List, + array: _.List, n: number): T[]; /** * @see _.first **/ - take(array: _.List): T; + take(array: _.List): T; /** * @see _.first **/ take( - array: _.List, + array: _.List, n: number): T[]; /** @@ -596,7 +596,7 @@ interface UnderscoreStatic { * @return Returns everything but the last `n` elements of `array`. **/ initial( - array: _.List, + array: _.List, n?: number): T[]; /** @@ -604,14 +604,14 @@ interface UnderscoreStatic { * @param array Retrieves the last element of this array. * @return Returns the last element of `array`. **/ - last(array: _.List): T; + last(array: _.List): T; /** * @see _.last * @param n Return more than one element from `array`. **/ last( - array: _.List, + array: _.List, n: number): T[]; /** @@ -622,21 +622,21 @@ interface UnderscoreStatic { * @return Returns the elements of `array` from `index` to the end of `array`. **/ rest( - array: _.List, + array: _.List, n?: number): T[]; /** * @see _.rest **/ tail( - array: _.List, + array: _.List, n?: number): T[]; /** * @see _.rest **/ drop( - array: _.List, + array: _.List, n?: number): T[]; /** @@ -645,7 +645,7 @@ interface UnderscoreStatic { * @param array Array to compact. * @return Copy of `array` without false values. **/ - compact(array: _.List): T[]; + compact(array: _.List): T[]; /** * Flattens a nested array (the nesting can be to any depth). If you pass shallow, the array will @@ -655,7 +655,7 @@ interface UnderscoreStatic { * @return `array` flattened. **/ flatten( - array: _.List, + array: _.List, shallow?: boolean): any[]; /** @@ -665,7 +665,7 @@ interface UnderscoreStatic { * @return Copy of `array` without `values`. **/ without( - array: _.List, + array: _.List, ...values: T[]): T[]; /** @@ -674,7 +674,7 @@ interface UnderscoreStatic { * @param arrays Array of arrays to compute the union of. * @return The union of elements within `arrays`. **/ - union(...arrays: _.List[]): T[]; + union(...arrays: _.List[]): T[]; /** * Computes the list of values that are the intersection of all the arrays. Each value in the result @@ -682,7 +682,7 @@ interface UnderscoreStatic { * @param arrays Array of arrays to compute the intersection of. * @return The intersection of elements within `arrays`. **/ - intersection(...arrays: _.List[]): T[]; + intersection(...arrays: _.List[]): T[]; /** * Similar to without, but returns the values from array that are not present in the other arrays. @@ -691,8 +691,8 @@ interface UnderscoreStatic { * @return Copy of `array` with only `others` values. **/ difference( - array: _.List, - ...others: _.List[]): T[]; + array: _.List, + ...others: _.List[]): T[]; /** * Produces a duplicate-free version of the array, using === to test object equality. If you know in @@ -705,34 +705,34 @@ interface UnderscoreStatic { * @return Copy of `array` where all elements are unique. **/ uniq( - array: _.List, + array: _.List, isSorted?: boolean, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): T[]; /** * @see _.uniq **/ uniq( - array: _.List, - iterator?: _.ListIterator, + array: _.List, + iterator?: _.ListIterator, context?: any): T[]; /** * @see _.uniq **/ unique( - array: _.List, - iterator?: _.ListIterator, + array: _.List, + iterator?: _.ListIterator, context?: any): T[]; /** * @see _.uniq **/ unique( - array: _.List, + array: _.List, isSorted?: boolean, - iterator?: _.ListIterator, + iterator?: _.ListIterator, context?: any): T[]; @@ -758,8 +758,8 @@ interface UnderscoreStatic { * @return An object containing the `keys` as properties and `values` as the property values. **/ object( - keys: _.List, - values: _.List): TResult; + keys: _.List, + values: _.List): TResult; /** * Converts arrays into objects. Pass either a single list of [key, value] pairs, or a @@ -773,7 +773,7 @@ interface UnderscoreStatic { * @see _.object **/ object( - list: _.List, + list: _.List, values?: any): TResult; /** @@ -787,7 +787,7 @@ interface UnderscoreStatic { * @return The index of `value` within `array`. **/ indexOf( - array: _.List, + array: _.List, value: T, isSorted?: boolean): number; @@ -795,7 +795,7 @@ interface UnderscoreStatic { * @see _indexof **/ indexOf( - array: _.List, + array: _.List, value: T, startFrom: number): number; @@ -808,7 +808,7 @@ interface UnderscoreStatic { * @return The index of the last occurance of `value` within `array`. **/ lastIndexOf( - array: _.List, + array: _.List, value: T, from?: number): number; @@ -822,7 +822,7 @@ interface UnderscoreStatic { * @return The index where `value` should be inserted into `list`. **/ sortedIndex( - list: _.List, + list: _.List, value: T, iterator?: (x: T) => TSort, context?: any): number; @@ -950,7 +950,7 @@ interface UnderscoreStatic { throttle( func: any, wait: number, - options?: _.ThrottleSettings): Function; + options?: _.ThrottleSettings): Function; /** * Creates and returns a new debounced version of the passed function that will postpone its execution @@ -1346,13 +1346,13 @@ interface UnderscoreStatic { * @param settings Settings to use while compiling. * @return Returns the compiled Underscore HTML template. **/ - template(templateString: string, data?: any, settings?: _.TemplateSettings): (...data: any[]) => string; + template(templateString: string, data?: any, settings?: _.TemplateSettings): (...data: any[]) => string; /** * By default, Underscore uses ERB-style template delimiters, change the * following template settings to use alternative delimiters. **/ - templateSettings: _.TemplateSettings; + templateSettings: _.TemplateSettings; /* ********** * Chaining * @@ -1364,8 +1364,8 @@ interface UnderscoreStatic { * @param obj Object to chain. * @return Wrapped `obj`. **/ - chain(obj: T[]): _Chain; - chain(obj: T): _Chain; + chain(obj: T[]): _Chain; + chain(obj: T): _Chain; /** * Extracts the value of a wrapped object. @@ -2195,8 +2195,10 @@ interface _Chain { * Wrapped type `any[]`. * @see _.map **/ - map(iterator: (value: T, index: number, list: T[]) => TArray[], context?: any): _ChainOfArrays; - //Not sure why this won't work, might be a TypeScript error? map(iterator: _.ListIterator, context?: any): _ChainOfArrays; + map(iterator: (value: T, index: number, list: T[]) => TArray[], context?: any): _ChainOfArrays; + //Not sure why this won't work, might be a TypeScript error? + //map(iterator: _.ListIterator, context?: any): _ChainOfArrays; + /** * Wrapped type `any[]`. * @see _.map @@ -2207,8 +2209,10 @@ interface _Chain { * Wrapped type `any[]`. * @see _.map **/ - map(iterator: (element: T, key: string, list: any) => TArray[], context?: any): _ChainOfArrays; - //Not sure why this won't work, might be a TypeScript error? //map(iterator: _.ObjectIterator, context?: any): _ChainOfArrays; + map(iterator: (element: T, key: string, list: any) => TArray[], context?: any): _ChainOfArrays; + //Not sure why this won't work, might be a TypeScript error? + //map(iterator: _.ObjectIterator, context?: any): _ChainOfArrays; + /** * Wrapped type `any[]`. * @see _.map @@ -2960,13 +2964,13 @@ interface _Chain { * Wrapped type `any`. * @see _.value **/ - value(): T[]; + value(): T[]; } interface _ChainSingle { - value(): T; + value(): T; } interface _ChainOfArrays extends _Chain { - flatten(): _Chain; + flatten(): _Chain; } declare var _: UnderscoreStatic;