Merge pull request #14494 from denisname/d3-array-strictNullChecks

Make d3-array work with stirctNullChecks
This commit is contained in:
Zhengbo Li
2017-02-17 13:49:03 -08:00
committed by GitHub
4 changed files with 145 additions and 211 deletions

View File

@@ -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, 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)];
@@ -62,7 +66,31 @@ 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<MixedObject>): number {
return datum.num;
}
function accessorMixedObjectToStr(datum: MixedObject, index: number, array: Array<MixedObject>): string {
return datum.str;
}
function accessorMixedObjectToNumeric(datum: MixedObject, index: number, array: Array<MixedObject>): NumCoercible {
return datum.numeric;
}
function accessorMixedObjectToDate(datum: MixedObject, index: number, array: Array<MixedObject>): Date {
return datum.date;
}
function accessorMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: Array<MixedObject | undefined>): number | undefined | null {
return datum ? datum.num : undefined;
}
function accessorMixedObjectToStrOrUndefined(datum: MixedObject | undefined, index: number, array: Array<MixedObject>): string | undefined | null {
return datum ? datum.str : undefined;
}
// -----------------------------------------------------------------------------
// Test Statistics
@@ -72,186 +100,109 @@ 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<MixedObject> = array;
return datum.num;
});
str = d3Array.max(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.str;
});
numeric = d3Array.max(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.numeric;
});
date = d3Array.max(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.date;
});
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() -----------------------------------------------------------------------
// 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<MixedObject> = array;
return datum.num;
});
str = d3Array.min(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.str;
});
numeric = d3Array.min(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.numeric;
});
date = d3Array.min(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.date;
});
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() --------------------------------------------------------------------
// without accessors
extentNum = d3Array.extent(numbersArray);
extentStr = d3Array.extent(stringyNumbersArray);
extentNumeric = d3Array.extent(numericArray);
extentDate = d3Array.extent(dateArray);
extentMixed = d3Array.extent<NumCoercible>([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<MixedObject> = array;
return datum.num;
});
extentStr = d3Array.extent(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.str;
});
extentMixed = d3Array.extent(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.numeric;
});
extentDateMixed = d3Array.extent(mixedObjectArray, function (datum, index, array) {
let d: MixedObject = datum;
let i: number = index;
let arr: Array<MixedObject> = array;
return datum.date;
});
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() ----------------------------------------------------------------------
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<MixedObject> = 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<MixedObject> = 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<MixedObject> = 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<MixedObject> = 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<MixedObject> = 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<MixedObject> = array;
return datum.num;
});
numOrUndefined = d3Array.variance(mixedObjectArray, accessorMixedObjectToNum);
numOrUndefined = d3Array.variance(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined);
// -----------------------------------------------------------------------------
// Test Searching Arrays
@@ -259,8 +210,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 +295,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 +327,11 @@ let testArrays: MixedObject[][] = [
]
];
let mergedArray: MixedObject[];
mergedArray = d3Array.merge(testArrays); // inferred type
mergedArray = d3Array.merge<MixedObject>(testArrays); // explicit type
// mergedArray = d3.merge<MixedObject>([[10, 40, 30], [15, 30]]); // fails, type mismatch
// mergedArray = d3Array.merge<MixedObject>([[10, 40, 30], [15, 30]]); // fails, type mismatch
// pairs() ---------------------------------------------------------------------

86
d3-array/index.d.ts vendored
View File

@@ -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 <https://github.com/gustavderdrache>, Boris Yankov <https://github.com/borisyankov>, Tom Wanzek <https://github.com/tomwanzek>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// Last module patch version validated against: 1.0.2
// --------------------------------------------------------------------------
// Shared Types and Interfaces
// --------------------------------------------------------------------------
@@ -20,17 +22,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,25 +37,15 @@ export function max(array: string[]): string | undefined;
*/
export function max<T extends Numeric>(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<T>(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.
*/
export function max<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => string): string | undefined;
export function max<T>(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<T, U extends Numeric>(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;
export function max<T, U extends Numeric>(array: T[], accessor: (datum: T, index: number, array: T[]) => U | undefined | null): U | undefined;
/**
* Return the minimum value in the array using natural order.
@@ -74,25 +60,15 @@ export function min<T extends Numeric>(array: T[]): T | undefined;
/**
* Return the minimum value in the array using natural order.
*/
export function min<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined;
export function min<T>(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<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => string): string | undefined;
/**
* Return the minimum value in the array using natural order.
*/
export function min<T, U extends Numeric>(array: T[], accessor: (datum: T, index: number, array: T[]) => U): U | undefined;
export function min<T, U extends Numeric>(array: T[], accessor: (datum: T, index: number, array: T[]) => U | undefined | null): U | undefined;
/**
* Return the min and max simultaneously.
*/
export function extent(array: number[]): [number, number] | [undefined, undefined];
/**
* Return the min and max simultaneously.
*/
@@ -106,79 +82,70 @@ export function extent<T extends Numeric>(array: T[]): [T, T] | [undefined, unde
/**
* Return the min and max simultaneously.
*/
export function extent<T extends Numeric>(array: Array<T | Primitive>): [T | Primitive, T | Primitive] | [undefined, undefined];
export function extent<T>(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<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => number): [number, number] | [undefined, undefined];
/**
* Return the min and max simultaneously.
*/
export function extent<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => string): [string, string] | [undefined, undefined];
/**
* Return the min and max simultaneously.
*/
export function extent<T, U extends Numeric>(array: T[], accessor: (datum: T, index: number, array: T[]) => U): [U, U ] | [undefined, undefined];
export function extent<T, U extends Numeric>(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: number[]): number | undefined;
export function mean<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined;
export function mean<T extends Numeric>(array: Array<T | undefined | null>): number | undefined;
export function mean<T>(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: number[]): number | undefined;
export function median<T>(array: T[], accessor: (element: T, i: number, array: T[]) => number): number | undefined;
export function median<T extends Numeric>(array: Array<T | undefined | null>): number | undefined;
export function median<T>(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: number[], p: number): number | undefined;
export function quantile<T>(array: T[], p: number, accessor: (element: T, i: number, array: T[]) => number): number | undefined;
export function quantile<T extends Numeric>(array: Array<T | undefined | null>, p: number): number | undefined;
export function quantile<T>(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: number[]): number;
export function sum<T extends Numeric>(array: Array<T | undefined | null>): number;
/**
* Compute the sum of an array, using the given accessor to convert values to numbers.
*/
export function sum<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number;
export function sum<T>(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: number[]): number | undefined;
export function deviation<T extends Numeric>(array: Array<T | undefined | null>): 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<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined;
export function deviation<T>(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: number[]): number | undefined;
export function variance<T extends Numeric>(array: Array<T | undefined | null>): 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<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => number): number | undefined;
export function variance<T>(array: T[], accessor: (datum: T, index: number, array: T[]) => number | undefined | null): number | undefined;
// --------------------------------------------------------------------------------------
// Searching Arrays
// --------------------------------------------------------------------------------------
export function scan<T>(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<T>(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;
@@ -202,16 +169,16 @@ export function bisector<T, U>(accessor: (x: T) => U): Bisector<T, U>;
/**
* 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
// --------------------------------------------------------------------------------------
@@ -236,7 +203,6 @@ export function permute<T>(array: { [key: number]: T }, keys: number[]): T[];
*/
export function permute<T>(object: { [key: string]: T }, keys: string[]): T[];
/**
* Generates a 0-based numeric sequence. The output range does not include 'stop'.
*/

View File

@@ -7,7 +7,7 @@
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": false,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"

6
d3-array/tslint.json Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": "../tslint.json",
"rules": {
"unified-signatures": false
}
}