From f928cdd8f35426322dd389169c3fe782a0cb8bfe Mon Sep 17 00:00:00 2001 From: denis Date: Tue, 7 Feb 2017 12:36:59 +0100 Subject: [PATCH 1/4] Make d3-array work with stirctNullChecks Add tslint.json Set strictNullChecks to true Changes variables names in tests Add accessors functions in tests Add tests for mean, median, quantile, sum, deviation, variance and scan Add undefined to Primitive type Remove useless declarations (number extends Numeric) Add unions of undefined where needed Improve permute with keyof --- d3-array/d3-array-tests.ts | 252 +++++++++++++++---------------------- d3-array/index.d.ts | 70 +++-------- d3-array/tsconfig.json | 2 +- d3-array/tslint.json | 6 + 4 files changed, 126 insertions(+), 204 deletions(-) create mode 100644 d3-array/tslint.json diff --git a/d3-array/d3-array-tests.ts b/d3-array/d3-array-tests.ts index 26ef2d3ef5..d000d0937b 100644 --- a/d3-array/d3-array-tests.ts +++ b/d3-array/d3-array-tests.ts @@ -25,7 +25,6 @@ class NumCoercible { } } - class MixedObject { public num: number; @@ -40,18 +39,23 @@ class MixedObject { this.date = date; } } + let num: number; -let str: string; -let numeric: NumCoercible; let date: Date; -let extentNum: [number, number]; -let extentStr: [string, string]; -let extentNumeric: [NumCoercible, NumCoercible]; -let extentDateMixed: [d3Array.Primitive, d3Array.Primitive]; -let extentMixed: [d3Array.Primitive | NumCoercible, d3Array.Primitive | NumCoercible]; -let extentDate: [Date, Date]; + +let numOrUndefined: number | undefined; +let strOrUndefined: string | undefined; +let numericOrUndefined: NumCoercible | undefined; +let dateOrUndefined: Date | undefined; +let numOrUndefinedExtent: [number, number] | [undefined, undefined]; +let strOrUndefinedExtent: [string, string] | [undefined, undefined]; +let numericOrUndefinedExtent: [NumCoercible, NumCoercible] | [undefined, undefined]; +let dateMixedOrUndefined: [Date , Date] | [undefined, undefined]; +let mixedOrUndefinedExtent: [d3Array.Primitive | NumCoercible, d3Array.Primitive | NumCoercible] | [undefined, undefined]; +let dateOrUndefinedExtent: [Date, Date] | [undefined, undefined]; let numbersArray = [10, 20, 30, 40, 50]; +let numbersOrUndefinedArray = [10, 20, undefined, 40, 50]; let stringyNumbersArray = ['10', '20', '30', '40', '50']; let numericArray = [new NumCoercible(10), new NumCoercible(20), new NumCoercible(30), new NumCoercible(40), new NumCoercible(50)]; let dateArray = [new Date(2016, 6, 1), new Date(2016, 7, 30), new Date(2015, 3, 15)]; @@ -62,7 +66,27 @@ let mixedObjectArray = [ new MixedObject(40, new Date(2014, 3, 15)), new MixedObject(50, new Date(2017, 4, 15)) ]; +let mixedObjectOrUndefinedArray = [...mixedObjectArray, undefined] +function accessorMixedObjectToNum(datum: MixedObject, index: number, array: Array): number { + return datum.num; +} + +function accessorMixedObjectToStr(datum: MixedObject, index: number, array: Array): string { + return datum.str; +} + +function accessorMixedObjectToNumeric(datum: MixedObject, index: number, array: Array): NumCoercible { + return datum.numeric; +} + +function accessorMixedObjectToDate(datum: MixedObject, index: number, array: Array): Date { + return datum.date; +} + +function accessorMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: Array): number | undefined { + return datum ? datum.num : undefined; +} // ----------------------------------------------------------------------------- // Test Statistics @@ -72,186 +96,103 @@ let mixedObjectArray = [ // without accessors -num = d3Array.max(numbersArray); -str = d3Array.max(stringyNumbersArray); -numeric = d3Array.max(numericArray); -date = d3Array.max(dateArray); +numOrUndefined = d3Array.max(numbersArray); +strOrUndefined = d3Array.max(stringyNumbersArray); +numericOrUndefined = d3Array.max(numericArray); +dateOrUndefined = d3Array.max(dateArray); // with accessors -num = d3Array.max(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); - -str = d3Array.max(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.str; -}); - -numeric = d3Array.max(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.numeric; -}); - -date = d3Array.max(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.date; -}); +numOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNum); +strOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToStr); +numericOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNumeric); +dateOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToDate); // min() ----------------------------------------------------------------------- // without accessors -num = d3Array.min(numbersArray); -str = d3Array.min(stringyNumbersArray); -numeric = d3Array.min(numericArray); -date = d3Array.min(dateArray); +numOrUndefined = d3Array.min(numbersArray); +strOrUndefined = d3Array.min(stringyNumbersArray); +numericOrUndefined = d3Array.min(numericArray); +dateOrUndefined = d3Array.min(dateArray); // with accessors -num = d3Array.min(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); - -str = d3Array.min(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.str; -}); - -numeric = d3Array.min(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.numeric; -}); - -date = d3Array.min(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.date; -}); +numOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNum); +strOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToStr); +numericOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNumeric); +dateOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToDate); // extent() -------------------------------------------------------------------- // without accessors -extentNum = d3Array.extent(numbersArray); -extentStr = d3Array.extent(stringyNumbersArray); -extentNumeric = d3Array.extent(numericArray); -extentDate = d3Array.extent(dateArray); -extentMixed = d3Array.extent([new NumCoercible(10), 13, '12', true]); +numOrUndefinedExtent = d3Array.extent(numbersArray); +strOrUndefinedExtent = d3Array.extent(stringyNumbersArray); +numericOrUndefinedExtent = d3Array.extent(numericArray); +dateOrUndefinedExtent = d3Array.extent(dateArray); // with accessors -extentNum = d3Array.extent(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); - -extentStr = d3Array.extent(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.str; -}); - -extentMixed = d3Array.extent(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.numeric; -}); - -extentDateMixed = d3Array.extent(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.date; -}); +numOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNum); +strOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToStr); +mixedOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNumeric); +dateMixedOrUndefined = d3Array.extent(mixedObjectArray, accessorMixedObjectToDate); // mean() ---------------------------------------------------------------------- -num = d3Array.mean(numbersArray); +numOrUndefined = d3Array.mean(numbersArray); +numOrUndefined = d3Array.mean(numericArray); +numOrUndefined = d3Array.mean(numbersOrUndefinedArray); -num = d3Array.mean(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); +numOrUndefined = d3Array.mean(mixedObjectArray, accessorMixedObjectToNum); +numOrUndefined = d3Array.mean(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); // median() -------------------------------------------------------------------- -num = d3Array.median(numbersArray); +numOrUndefined = d3Array.median(numbersArray); +numOrUndefined = d3Array.median(numericArray); +numOrUndefined = d3Array.median(numbersOrUndefinedArray); -num = d3Array.median(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); +numOrUndefined = d3Array.median(mixedObjectArray, accessorMixedObjectToNum); +numOrUndefined = d3Array.median(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); // quantile() ------------------------------------------------------------------ -num = d3Array.quantile(numbersArray, 0.5); +numOrUndefined = d3Array.quantile(numbersArray, 0.5); +numOrUndefined = d3Array.quantile(numericArray, 0.5); +numOrUndefined = d3Array.quantile(numbersOrUndefinedArray, 0.5); -num = d3Array.quantile(mixedObjectArray, 0.5, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); +numOrUndefined = d3Array.quantile(mixedObjectArray, 0.5, accessorMixedObjectToNum); +numOrUndefined = d3Array.quantile(mixedObjectOrUndefinedArray, 0.5, accessorMixedObjectToNumOrUndefined); // sum() ----------------------------------------------------------------------- +numOrUndefined = d3Array.sum(numbersArray); +numOrUndefined = d3Array.sum(numericArray); +numOrUndefined = d3Array.sum(numbersOrUndefinedArray); -num = d3Array.sum(numbersArray); - -num = d3Array.sum(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); +numOrUndefined = d3Array.sum(mixedObjectArray, accessorMixedObjectToNum); +numOrUndefined = d3Array.sum(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); // deviation() ----------------------------------------------------------------- -num = d3Array.deviation(numbersArray); +numOrUndefined = d3Array.deviation(numbersArray); +numOrUndefined = d3Array.deviation(numericArray); +numOrUndefined = d3Array.deviation(numbersOrUndefinedArray); -num = d3Array.deviation(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); +numOrUndefined = d3Array.deviation(mixedObjectArray, accessorMixedObjectToNum); +numOrUndefined = d3Array.deviation(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); // variance() ------------------------------------------------------------------ -num = d3Array.variance(numbersArray); +numOrUndefined = d3Array.variance(numbersArray); +numOrUndefined = d3Array.variance(numericArray); +numOrUndefined = d3Array.variance(numbersOrUndefinedArray); -num = d3Array.variance(mixedObjectArray, function (datum, index, array) { - let d: MixedObject = datum; - let i: number = index; - let arr: Array = array; - return datum.num; -}); +numOrUndefined = d3Array.variance(mixedObjectArray, accessorMixedObjectToNum); +numOrUndefined = d3Array.variance(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); // ----------------------------------------------------------------------------- // Test Searching Arrays @@ -259,8 +200,18 @@ num = d3Array.variance(mixedObjectArray, function (datum, index, array) { // scan() ---------------------------------------------------------------------- -num = d3Array.scan(mixedObjectArray, function (a, b) { - return a.num - b.num; // a and b are of type MixedObject +numOrUndefined = d3Array.scan(numbersArray) + +numOrUndefined = d3Array.scan(mixedObjectArray, function (a, b) { + let aElem: MixedObject = a; + let bElem: MixedObject = b; + return a.num - b.num; +}); + +numOrUndefined = d3Array.scan(mixedObjectOrUndefinedArray, function (a, b) { + let aElem: MixedObject | undefined = a; + let bElem: MixedObject | undefined = b; + return a && b ? a.num - b.num : NaN; }); // bisectLeft() ---------------------------------------------------------------- @@ -334,12 +285,14 @@ num = mixedObjectDateBisectorObject.right(mixedObjectArray, new Date(2015, 3, 14 // ascending() ----------------------------------------------------------------- +num = d3Array.ascending(undefined, 20); num = d3Array.ascending(10, 20); num = d3Array.ascending('10', '20'); num = d3Array.ascending(new Date(2016, 6, 13), new Date(2016, 6, 14)); // descending() ---------------------------------------------------------------- +num = d3Array.descending(undefined, 20); num = d3Array.descending(10, 20); num = d3Array.descending('10', '20'); num = d3Array.descending(new Date(2016, 6, 13), new Date(2016, 6, 14)); @@ -364,12 +317,11 @@ let testArrays: MixedObject[][] = [ ] ]; - let mergedArray: MixedObject[]; mergedArray = d3Array.merge(testArrays); // inferred type mergedArray = d3Array.merge(testArrays); // explicit type -// mergedArray = d3.merge([[10, 40, 30], [15, 30]]); // fails, type mismatch +// mergedArray = d3Array.merge([[10, 40, 30], [15, 30]]); // fails, type mismatch // pairs() --------------------------------------------------------------------- diff --git a/d3-array/index.d.ts b/d3-array/index.d.ts index e3bd2d549d..8bcfeb7519 100644 --- a/d3-array/index.d.ts +++ b/d3-array/index.d.ts @@ -11,7 +11,7 @@ /** * Administrivia: JavaScript primitive types and Date */ -export type Primitive = number | string | boolean | Date; +export type Primitive = number | string | boolean | Date | undefined; /** * Administrivia: anything with a valueOf(): number method is comparable, so we allow it in numeric operations @@ -20,17 +20,11 @@ interface Numeric { valueOf(): number; } - // -------------------------------------------------------------------------------------- // Descriptive Statistics // -------------------------------------------------------------------------------------- -/** - * Return the maximum value in the array of numbers using natural order. - */ -export function max(array: number[]): number | undefined; - /** * Return the maximum value in the array of strings using natural order. */ @@ -41,11 +35,6 @@ export function max(array: string[]): string | undefined; */ export function max(array: T[]): T | undefined; -/** - * Return the maximum value in the array using natural order and a projection function to map values to numbers. - */ -export function max(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined; - /** * Return the maximum value in the array using natural order and a projection function to map values to strings. */ @@ -56,11 +45,6 @@ export function max(array: T[], accessor: (datum: T, index: number, array: T[ */ export function max(array: T[], accessor: (datum: T, index: number, array: T[]) => U): U | undefined; -/** - * Return the minimum value in the array using natural order. - */ -export function min(array: number[]): number | undefined; - /** * Return the minimum value in the array using natural order. */ @@ -71,11 +55,6 @@ export function min(array: string[]): string | undefined; */ export function min(array: T[]): T | undefined; -/** - * Return the minimum value in the array using natural order. - */ -export function min(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined; - /** * Return the minimum value in the array using natural order. */ @@ -88,11 +67,6 @@ export function min(array: T[], accessor: (datum: T, index -/** - * Return the min and max simultaneously. - */ -export function extent(array: number[]): [number, number] | [undefined, undefined]; - /** * Return the min and max simultaneously. */ @@ -103,16 +77,6 @@ export function extent(array: string[]): [string, string] | [undefined, undefine */ export function extent(array: T[]): [T, T] | [undefined, undefined]; -/** - * Return the min and max simultaneously. - */ -export function extent(array: Array): [T | Primitive, T | Primitive] | [undefined, undefined]; - -/** - * Return the min and max simultaneously. - */ -export function extent(array: T[], accessor: (datum: T, index: number, array: T[]) => number): [number, number] | [undefined, undefined]; - /** * Return the min and max simultaneously. */ @@ -121,64 +85,65 @@ export function extent(array: T[], accessor: (datum: T, index: number, array: /** * Return the min and max simultaneously. */ -export function extent(array: T[], accessor: (datum: T, index: number, array: T[]) => U): [U, U ] | [undefined, undefined]; +export function extent(array: T[], accessor: (datum: T, index: number, array: T[]) => U): [U, U] | [undefined, undefined]; /** * Return the mean of an array of numbers */ -export function mean(array: number[]): number | undefined; -export function mean(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined; +export function mean(array: (T | undefined)[]): number | undefined; +export function mean(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number | undefined; /** * Return the median of an array of numbers */ -export function median(array: number[]): number | undefined; -export function median(array: T[], accessor: (element: T, i: number, array: T[]) => number): number | undefined; +export function median(array: (T | undefined)[]): number | undefined; +export function median(array: T[], accessor: (element: T, i: number, array: T[]) => number | undefined): number | undefined; /** * Returns the p-quantile of an array of numbers */ -export function quantile(array: number[], p: number): number | undefined; -export function quantile(array: T[], p: number, accessor: (element: T, i: number, array: T[]) => number): number | undefined; +export function quantile(array: (T | undefined)[], p: number): number | undefined; +export function quantile(array: T[], p: number, accessor: (element: T, i: number, array: T[]) => number | undefined): number | undefined; /** * Compute the sum of an array of numbers. */ -export function sum(array: number[]): number; +export function sum(array: (T | undefined)[]): number; /** * Compute the sum of an array, using the given accessor to convert values to numbers. */ -export function sum(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number; +export function sum(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number; /** * Compute the standard deviation, defined as the square root of the bias-corrected variance, of the given array of numbers. */ -export function deviation(array: number[]): number | undefined; +export function deviation(array: (T | undefined)[]): number | undefined; /** * Compute the standard deviation, defined as the square root of the bias-corrected variance, of the given array, * using the given accessor to convert values to numbers. */ -export function deviation(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined; +export function deviation(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number | undefined; /** * Compute an unbiased estimator of the population variance of the given array of numbers. */ -export function variance(array: number[]): number | undefined; +export function variance(array: (T | undefined)[]): number | undefined; /** * Compute an unbiased estimator of the population variance of the given array, * using the given accessor to convert values to numbers. */ -export function variance(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined; +export function variance(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number | undefined; // -------------------------------------------------------------------------------------- // Searching Arrays // -------------------------------------------------------------------------------------- -export function scan(array: T[], comparator: (a: T, b: T) => number): number; +export function scan(array: number[], comparator?: (a: number, b: number) => number): number | undefined; +export function scan(array: T[], comparator: (a: T, b: T) => number): number | undefined; export function bisectLeft(array: number[], x: number, lo?: number, hi?: number): number; export function bisectLeft(array: string[], x: string, lo?: number, hi?: number): number; @@ -234,8 +199,7 @@ export function permute(array: { [key: number]: T }, keys: number[]): T[]; /** * Given the specified object, return an array corresponding to the list of property names in 'keys'. */ -export function permute(object: { [key: string]: T }, keys: string[]): T[]; - +export function permute(object: T, keys: K[]): T[K][]; /** * Generates a 0-based numeric sequence. The output range does not include 'stop'. diff --git a/d3-array/tsconfig.json b/d3-array/tsconfig.json index db900a4087..b70f6aed80 100644 --- a/d3-array/tsconfig.json +++ b/d3-array/tsconfig.json @@ -7,7 +7,7 @@ ], "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" diff --git a/d3-array/tslint.json b/d3-array/tslint.json new file mode 100644 index 0000000000..68d10d72a6 --- /dev/null +++ b/d3-array/tslint.json @@ -0,0 +1,6 @@ +{ + "extends": "../tslint.json", + "rules": { + "unified-signatures": false + } +} From 879484cf6fabbc601c6681eba4afd1357b6da607 Mon Sep 17 00:00:00 2001 From: denis Date: Wed, 8 Feb 2017 17:51:55 +0100 Subject: [PATCH 2/4] Set back permute definition Typescript 2.1 make travis fail --- d3-array/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/d3-array/index.d.ts b/d3-array/index.d.ts index 8bcfeb7519..371a60b52b 100644 --- a/d3-array/index.d.ts +++ b/d3-array/index.d.ts @@ -199,7 +199,7 @@ export function permute(array: { [key: number]: T }, keys: number[]): T[]; /** * Given the specified object, return an array corresponding to the list of property names in 'keys'. */ -export function permute(object: T, keys: K[]): T[K][]; +export function permute(object: { [key: string]: T }, keys: string[]): T[]; /** * Generates a 0-based numeric sequence. The output range does not include 'stop'. From 3d45e75897123977fa1a5842cdb9745c898f33cc Mon Sep 17 00:00:00 2001 From: denis Date: Wed, 8 Feb 2017 18:33:50 +0100 Subject: [PATCH 3/4] Linting Errors given by tslint: * Array type using 'T[]' is forbidden for non-simple types. Use 'Array' instead. * Error parsing header. Expected: foo MAJOR.MINOR (patch version not allowed) --- d3-array/index.d.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/d3-array/index.d.ts b/d3-array/index.d.ts index 371a60b52b..eacd712e15 100644 --- a/d3-array/index.d.ts +++ b/d3-array/index.d.ts @@ -1,8 +1,10 @@ -// Type definitions for D3JS d3-array module v1.0.1 +// Type definitions for D3JS d3-array module 1.0 // Project: https://github.com/d3/d3-array // Definitions by: Alex Ford , Boris Yankov , Tom Wanzek // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// Last module patch version validated against: 1.0.2 + // -------------------------------------------------------------------------- // Shared Types and Interfaces // -------------------------------------------------------------------------- @@ -90,25 +92,25 @@ export function extent(array: T[], accessor: (datum: T, in /** * Return the mean of an array of numbers */ -export function mean(array: (T | undefined)[]): number | undefined; +export function mean(array: Array): number | undefined; export function mean(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number | undefined; /** * Return the median of an array of numbers */ -export function median(array: (T | undefined)[]): number | undefined; +export function median(array: Array): number | undefined; export function median(array: T[], accessor: (element: T, i: number, array: T[]) => number | undefined): number | undefined; /** * Returns the p-quantile of an array of numbers */ -export function quantile(array: (T | undefined)[], p: number): number | undefined; +export function quantile(array: Array, p: number): number | undefined; export function quantile(array: T[], p: number, accessor: (element: T, i: number, array: T[]) => number | undefined): number | undefined; /** * Compute the sum of an array of numbers. */ -export function sum(array: (T | undefined)[]): number; +export function sum(array: Array): number; /** * Compute the sum of an array, using the given accessor to convert values to numbers. @@ -118,7 +120,7 @@ export function sum(array: T[], accessor: (datum: T, index: number, array: T[ /** * Compute the standard deviation, defined as the square root of the bias-corrected variance, of the given array of numbers. */ -export function deviation(array: (T | undefined)[]): number | undefined; +export function deviation(array: Array): number | undefined; /** * Compute the standard deviation, defined as the square root of the bias-corrected variance, of the given array, @@ -129,7 +131,7 @@ export function deviation(array: T[], accessor: (datum: T, index: number, arr /** * Compute an unbiased estimator of the population variance of the given array of numbers. */ -export function variance(array: (T | undefined)[]): number | undefined; +export function variance(array: Array): number | undefined; /** * Compute an unbiased estimator of the population variance of the given array, From 681bde5adfb3f8d7bfb61faa83280986e6b9f0fe Mon Sep 17 00:00:00 2001 From: denis Date: Wed, 15 Feb 2017 12:22:40 +0100 Subject: [PATCH 4/4] d3.max, d3.min and d3.extent allows accessor to return undefined or null remove undefined from Primitive add null as possible d3-array statistics value --- d3-array/d3-array-tests.ts | 14 ++++++++++-- d3-array/index.d.ts | 44 +++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/d3-array/d3-array-tests.ts b/d3-array/d3-array-tests.ts index d000d0937b..e086fd2502 100644 --- a/d3-array/d3-array-tests.ts +++ b/d3-array/d3-array-tests.ts @@ -55,7 +55,7 @@ let mixedOrUndefinedExtent: [d3Array.Primitive | NumCoercible, d3Array.Primitive let dateOrUndefinedExtent: [Date, Date] | [undefined, undefined]; let numbersArray = [10, 20, 30, 40, 50]; -let numbersOrUndefinedArray = [10, 20, undefined, 40, 50]; +let numbersOrUndefinedArray = [10, 20, undefined, null, 40, 50]; let stringyNumbersArray = ['10', '20', '30', '40', '50']; let numericArray = [new NumCoercible(10), new NumCoercible(20), new NumCoercible(30), new NumCoercible(40), new NumCoercible(50)]; let dateArray = [new Date(2016, 6, 1), new Date(2016, 7, 30), new Date(2015, 3, 15)]; @@ -84,10 +84,14 @@ function accessorMixedObjectToDate(datum: MixedObject, index: number, array: Arr return datum.date; } -function accessorMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: Array): number | undefined { +function accessorMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: Array): number | undefined | null { return datum ? datum.num : undefined; } +function accessorMixedObjectToStrOrUndefined(datum: MixedObject | undefined, index: number, array: Array): string | undefined | null { + return datum ? datum.str : undefined; +} + // ----------------------------------------------------------------------------- // Test Statistics // ----------------------------------------------------------------------------- @@ -107,6 +111,8 @@ numOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNum); strOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToStr); numericOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNumeric); dateOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToDate); +numOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNumOrUndefined); +strOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToStrOrUndefined); // min() ----------------------------------------------------------------------- @@ -123,6 +129,8 @@ numOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNum); strOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToStr); numericOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNumeric); dateOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToDate); +numOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNumOrUndefined); +strOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToStrOrUndefined); // extent() -------------------------------------------------------------------- @@ -139,6 +147,8 @@ numOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNum strOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToStr); mixedOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNumeric); dateMixedOrUndefined = d3Array.extent(mixedObjectArray, accessorMixedObjectToDate); +numOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNumOrUndefined); +strOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToStrOrUndefined); // mean() ---------------------------------------------------------------------- diff --git a/d3-array/index.d.ts b/d3-array/index.d.ts index eacd712e15..336eb2bc83 100644 --- a/d3-array/index.d.ts +++ b/d3-array/index.d.ts @@ -13,7 +13,7 @@ /** * Administrivia: JavaScript primitive types and Date */ -export type Primitive = number | string | boolean | Date | undefined; +export type Primitive = number | string | boolean | Date; /** * Administrivia: anything with a valueOf(): number method is comparable, so we allow it in numeric operations @@ -40,12 +40,12 @@ export function max(array: T[]): T | undefined; /** * Return the maximum value in the array using natural order and a projection function to map values to strings. */ -export function max(array: T[], accessor: (datum: T, index: number, array: T[]) => string): string | undefined; +export function max(array: T[], accessor: (datum: T, index: number, array: T[]) => string | undefined | null): string | undefined; /** * Return the maximum value in the array using natural order and a projection function to map values to easily-sorted values. */ -export function max(array: T[], accessor: (datum: T, index: number, array: T[]) => U): U | undefined; +export function max(array: T[], accessor: (datum: T, index: number, array: T[]) => U | undefined | null): U | undefined; /** * Return the minimum value in the array using natural order. @@ -60,12 +60,12 @@ export function min(array: T[]): T | undefined; /** * Return the minimum value in the array using natural order. */ -export function min(array: T[], accessor: (datum: T, index: number, array: T[]) => string): string | undefined; +export function min(array: T[], accessor: (datum: T, index: number, array: T[]) => string | undefined | null): string | undefined; /** * Return the minimum value in the array using natural order. */ -export function min(array: T[], accessor: (datum: T, index: number, array: T[]) => U): U | undefined; +export function min(array: T[], accessor: (datum: T, index: number, array: T[]) => U | undefined | null): U | undefined; @@ -82,62 +82,62 @@ export function extent(array: T[]): [T, T] | [undefined, unde /** * Return the min and max simultaneously. */ -export function extent(array: T[], accessor: (datum: T, index: number, array: T[]) => string): [string, string] | [undefined, undefined]; +export function extent(array: T[], accessor: (datum: T, index: number, array: T[]) => string | undefined | null): [string, string] | [undefined, undefined]; /** * Return the min and max simultaneously. */ -export function extent(array: T[], accessor: (datum: T, index: number, array: T[]) => U): [U, U] | [undefined, undefined]; +export function extent(array: T[], accessor: (datum: T, index: number, array: T[]) => U | undefined | null): [U, U] | [undefined, undefined]; /** * Return the mean of an array of numbers */ -export function mean(array: Array): number | undefined; -export function mean(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number | undefined; +export function mean(array: Array): number | undefined; +export function mean(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined | null): number | undefined; /** * Return the median of an array of numbers */ -export function median(array: Array): number | undefined; -export function median(array: T[], accessor: (element: T, i: number, array: T[]) => number | undefined): number | undefined; +export function median(array: Array): number | undefined; +export function median(array: T[], accessor: (element: T, i: number, array: T[]) => number | undefined | null): number | undefined; /** * Returns the p-quantile of an array of numbers */ -export function quantile(array: Array, p: number): number | undefined; -export function quantile(array: T[], p: number, accessor: (element: T, i: number, array: T[]) => number | undefined): number | undefined; +export function quantile(array: Array, p: number): number | undefined; +export function quantile(array: T[], p: number, accessor: (element: T, i: number, array: T[]) => number | undefined | null): number | undefined; /** * Compute the sum of an array of numbers. */ -export function sum(array: Array): number; +export function sum(array: Array): number; /** * Compute the sum of an array, using the given accessor to convert values to numbers. */ -export function sum(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number; +export function sum(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined | null): number; /** * Compute the standard deviation, defined as the square root of the bias-corrected variance, of the given array of numbers. */ -export function deviation(array: Array): number | undefined; +export function deviation(array: Array): number | undefined; /** * Compute the standard deviation, defined as the square root of the bias-corrected variance, of the given array, * using the given accessor to convert values to numbers. */ -export function deviation(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number | undefined; +export function deviation(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined | null): number | undefined; /** * Compute an unbiased estimator of the population variance of the given array of numbers. */ -export function variance(array: Array): number | undefined; +export function variance(array: Array): number | undefined; /** * Compute an unbiased estimator of the population variance of the given array, * using the given accessor to convert values to numbers. */ -export function variance(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined): number | undefined; +export function variance(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined | null): number | undefined; // -------------------------------------------------------------------------------------- @@ -169,16 +169,16 @@ export function bisector(accessor: (x: T) => U): Bisector; /** * Compares two primitive values for sorting (in ascending order). */ -export function ascending(a: Primitive, b: Primitive): number; +export function ascending(a: Primitive | undefined, b: Primitive | undefined): number; // NB. this is limited to primitive values due to D3's use of the <, >, and >= operators. Results get weird for object instances. /** * Compares two primitive values for sorting (in ascending order). */ -export function descending(a: Primitive, b: Primitive): number; +export function descending(a: Primitive | undefined, b: Primitive | undefined): number; // -------------------------------------------------------------------------------------- -// Transforming Arrays +// Transforming Arrays // --------------------------------------------------------------------------------------