diff --git a/types/d3-array/d3-array-tests.ts b/types/d3-array/d3-array-tests.ts index 42bf95bcfe..1c6cbcaea8 100644 --- a/types/d3-array/d3-array-tests.ts +++ b/types/d3-array/d3-array-tests.ts @@ -40,12 +40,14 @@ class MixedObject { } let num: number; -let date: Date; +let undef: undefined; +let mixedObject: MixedObject; let numOrUndefined: number | undefined; let strOrUndefined: string | undefined; let numericOrUndefined: NumCoercible | undefined; let dateOrUndefined: Date | undefined; +let mixedObjectOrUndefined: MixedObject | undefined; let numOrUndefinedExtent: [number, number] | [undefined, undefined]; let strOrUndefinedExtent: [string, string] | [undefined, undefined]; let numericOrUndefinedExtent: [NumCoercible, NumCoercible] | [undefined, undefined]; @@ -68,6 +70,7 @@ const mixedObjectArray = [ ]; const mixedObjectOrUndefinedArray = [...mixedObjectArray, undefined]; +const mixedObjectArrayLike = mixedObjectArray as ArrayLike; let typedArray = Uint8Array.from(numbersArray); let readonlyNumbersArray = numbersArray as ReadonlyArray; @@ -76,32 +79,60 @@ const readonlyStringyNumbersArray = stringyNumbersArray as ReadonlyArray const readonlyNumericArray = numericArray as ReadonlyArray; const readonlyDateArray = dateArray as ReadonlyArray; const readonlyMixedObjectArray = mixedObjectArray as ReadonlyArray; -const readonlyMixedObjectOrUndefinedArray = mixedObjectOrUndefinedArray as ReadonlyArray; +const readonlyMixedObjectOrUndefinedArray = mixedObjectOrUndefinedArray as ReadonlyArray; -function accessorMixedObjectToNum(datum: MixedObject, index: number, array: MixedObject[]): number { +function accessorMixedObjectToNum(datum: MixedObject, index: number, array: ArrayLike): number { return datum.num; } -function accessorMixedObjectToStr(datum: MixedObject, index: number, array: MixedObject[]): string { +function accessorMixedObjectToStr(datum: MixedObject, index: number, array: ArrayLike): string { return datum.str; } -function accessorMixedObjectToNumeric(datum: MixedObject, index: number, array: MixedObject[]): NumCoercible { +function accessorMixedObjectToNumeric(datum: MixedObject, index: number, array: ArrayLike): NumCoercible { return datum.numeric; } -function accessorMixedObjectToDate(datum: MixedObject, index: number, array: MixedObject[]): Date { +function accessorMixedObjectToDate(datum: MixedObject, index: number, array: ArrayLike): Date { return datum.date; } -function accessorMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: Array): number | undefined | null { +function accessorMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: ArrayLike): number | undefined | null { return datum ? datum.num : undefined; } -function accessorMixedObjectToStrOrUndefined(datum: MixedObject | undefined, index: number, array: MixedObject[]): string | undefined | null { +function accessorMixedObjectToStrOrUndefined(datum: MixedObject | undefined, index: number, array: ArrayLike): string | undefined | null { return datum ? datum.str : undefined; } +function accessorLikeMixedObjectToNum(datum: MixedObject, index: number, array: ArrayLike): number { + return datum.num; +} + +function accessorLikeMixedObjectToStr(datum: MixedObject, index: number, array: ArrayLike): string { + return datum.str; +} + +function accessorLikeMixedObjectToNumeric(datum: MixedObject, index: number, array: ArrayLike): NumCoercible { + return datum.numeric; +} + +function accessorLikeMixedObjectToDate(datum: MixedObject, index: number, array: ArrayLike): Date { + return datum.date; +} + +function accessorLikeMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: ArrayLike): number | undefined | null { + return datum ? datum.num : undefined; +} + +function accessorLikeMixedObjectToStrOrUndefined(datum: MixedObject | undefined, index: number, array: ArrayLike): string | undefined | null { + return datum ? datum.str : undefined; +} + +function accessorReadOnlyMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: ArrayLike): number | undefined | null { + return datum ? datum.num : undefined; +} + // ----------------------------------------------------------------------------- // Test Statistics // ----------------------------------------------------------------------------- @@ -131,7 +162,24 @@ numericOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNumeric) dateOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToDate); numOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNumOrUndefined); strOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToStrOrUndefined); -numOrUndefined = d3Array.max(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.max(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); + +numOrUndefined = d3Array.max(mixedObjectArrayLike, accessorLikeMixedObjectToNum); +numOrUndefined = d3Array.max(mixedObjectArray, accessorLikeMixedObjectToNum); +numOrUndefined = d3Array.max(mixedObjectArray, accessorReadOnlyMixedObjectToNumOrUndefined); + +numOrUndefined = d3Array.max(mixedObjectArray, (d) => { + const l: MixedObject = d; + return l.num; +}); + +strOrUndefined = d3Array.max(mixedObjectArray, (d) => { + const l: MixedObject = d; + return l.str; +}); + +// $ExpectError +numOrUndefined = d3Array.max(readonlyNumbersArray, (d, i, a) => { a.push(3); return 0; }); // min() ----------------------------------------------------------------------- @@ -158,7 +206,7 @@ numericOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNumeric) dateOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToDate); numOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNumOrUndefined); strOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToStrOrUndefined); -numOrUndefined = d3Array.max(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.min(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); // extent() -------------------------------------------------------------------- @@ -185,7 +233,7 @@ mixedOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToN dateMixedOrUndefined = d3Array.extent(mixedObjectArray, accessorMixedObjectToDate); numOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNumOrUndefined); strOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToStrOrUndefined); -numOrUndefinedExtent = d3Array.extent(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefinedExtent = d3Array.extent(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); // mean() ---------------------------------------------------------------------- @@ -200,7 +248,7 @@ numOrUndefined = d3Array.mean(readonlyNumbersOrUndefinedArray); numOrUndefined = d3Array.mean(mixedObjectArray, accessorMixedObjectToNum); numOrUndefined = d3Array.mean(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); -numOrUndefined = d3Array.mean(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.mean(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); // median() -------------------------------------------------------------------- @@ -215,7 +263,7 @@ numOrUndefined = d3Array.median(readonlyNumbersOrUndefinedArray); numOrUndefined = d3Array.median(mixedObjectArray, accessorMixedObjectToNum); numOrUndefined = d3Array.median(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); -numOrUndefined = d3Array.median(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.median(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); // quantile() ------------------------------------------------------------------ @@ -230,7 +278,7 @@ numOrUndefined = d3Array.quantile(readonlyNumbersOrUndefinedArray, 0.5); numOrUndefined = d3Array.quantile(mixedObjectArray, 0.5, accessorMixedObjectToNum); numOrUndefined = d3Array.quantile(mixedObjectOrUndefinedArray, 0.5, accessorMixedObjectToNumOrUndefined); -numOrUndefined = d3Array.quantile(readonlyMixedObjectOrUndefinedArray, 0.5, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.quantile(readonlyMixedObjectOrUndefinedArray, 0.5, accessorReadOnlyMixedObjectToNumOrUndefined); // sum() ----------------------------------------------------------------------- @@ -245,7 +293,7 @@ numOrUndefined = d3Array.sum(readonlyNumbersOrUndefinedArray); numOrUndefined = d3Array.sum(mixedObjectArray, accessorMixedObjectToNum); numOrUndefined = d3Array.sum(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); -numOrUndefined = d3Array.sum(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.sum(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); // deviation() ----------------------------------------------------------------- @@ -260,7 +308,7 @@ numOrUndefined = d3Array.deviation(readonlyNumbersOrUndefinedArray); numOrUndefined = d3Array.deviation(mixedObjectArray, accessorMixedObjectToNum); numOrUndefined = d3Array.deviation(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); -numOrUndefined = d3Array.deviation(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.deviation(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); // variance() ------------------------------------------------------------------ @@ -275,7 +323,7 @@ numOrUndefined = d3Array.variance(readonlyNumbersOrUndefinedArray); numOrUndefined = d3Array.variance(mixedObjectArray, accessorMixedObjectToNum); numOrUndefined = d3Array.variance(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); -numOrUndefined = d3Array.variance(readonlyMixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined); +numOrUndefined = d3Array.variance(readonlyMixedObjectOrUndefinedArray, accessorReadOnlyMixedObjectToNumOrUndefined); // ----------------------------------------------------------------------------- // Test Searching Arrays @@ -480,8 +528,10 @@ let mergedArray: MixedObject[]; mergedArray = d3Array.merge(testArrays); // inferred type mergedArray = d3Array.merge(testArrays); // explicit type -// mergedArray = d3Array.merge([[10, 40, 30], [15, 30]]); // fails, type mismatch -// mergedArray = d3Array.merge([testArray1, [15, 30]]); // fails, type mismatch +// $ExpectError +mergedArray = d3Array.merge([[10, 40, 30], [15, 30]]); // fails, type mismatch +// $ExpectError +mergedArray = d3Array.merge([testArray1, [15, 30]]); // fails, type mismatch mergedArray = d3Array.merge(readonlyTestArrays); // inferred type mergedArray = d3Array.merge(readonlyTestArrays); // explicit type @@ -569,7 +619,8 @@ numbersArray = d3Array.range(1, 10, 0.5); mergedArray = d3Array.shuffle(mergedArray); mergedArray = d3Array.shuffle(mergedArray, 1); mergedArray = d3Array.shuffle(mergedArray, 1, 3); -// mergedArray = d3Array.shuffle(readonlyMergedArray); // fails, shuffle mutates input array in-place +// $ExpectError +mergedArray = d3Array.shuffle(readonlyMergedArray); // fails, shuffle mutates input array in-place // Test each TypedArray explicitly. Can't use ArrayLike in this case because shuffle is mutable and ArrayLike would include ReadonlyArray const resultInt8: Int8Array = d3Array.shuffle(new Int8Array(numbersArray)); @@ -608,96 +659,259 @@ testArrays = d3Array.zip(readonlyTestArray1, readonlyTestArray2); // Test Histogram // ----------------------------------------------------------------------------- -const tScale = scaleTime(); +const timeScale = scaleTime(); // Create histogram generator ================================================== -let defaultHistogram: d3Array.HistogramGenerator; -defaultHistogram = d3Array.histogram(); +// number - number +let histoNumber_Number: d3Array.HistogramGeneratorNumber; +histoNumber_Number = d3Array.histogram(); +histoNumber_Number = d3Array.histogram(); -let testHistogram: d3Array.HistogramGenerator; -testHistogram = d3Array.histogram(); +// MixedObject - number | undefined +let histoMixed_NumberOrUndefined: d3Array.HistogramGeneratorNumber; +histoMixed_NumberOrUndefined = d3Array.histogram(); + +// MixedObject | undefined - number | undefined +let histoMixedOrUndefined_NumberOrUndefined: d3Array.HistogramGeneratorNumber; +histoMixedOrUndefined_NumberOrUndefined = d3Array.histogram(); + +// MixedObject | undefined - number +let histoMixedOrUndefined_Number: d3Array.HistogramGeneratorNumber; +histoMixedOrUndefined_Number = d3Array.histogram(); + +// MixedObject - Date +let histoMixedObject_Date: d3Array.HistogramGeneratorDate; +histoMixedObject_Date = d3Array.histogram(); + +// MixedObject - Date | undefined +let histoMixedObject_DateOrUndefined: d3Array.HistogramGeneratorDate; +histoMixedObject_DateOrUndefined = d3Array.histogram(); + +let defaultHistogram: d3Array.HistogramGeneratorNumber; +defaultHistogram = d3Array.histogram(); // Configure histogram generator =============================================== // value(...) ------------------------------------------------------------------ -testHistogram = testHistogram.value((d, i, data) => { - const datum: MixedObject = d; // d is of type MixedObject - const index: number = i; // i is number - const array: ArrayLike = data; // data is of type MixedObject[] - return datum.date; +let valueAccessorFn: (d: MixedObject, i: number, data: MixedObject[]) => Date; +valueAccessorFn = histoMixedObject_Date.value(); + +type valueAccessor = (d: D, i: number, data: D[]) => V; + +// number - number +const valueFnNumber_Number: valueAccessor = histoNumber_Number.value(); +histoNumber_Number = histoNumber_Number.value((d: number, i: number, data: ArrayLike) => { + return d - num; }); -let valueAccessorFn: (d: MixedObject, i: number, data: MixedObject[]) => Date; -valueAccessorFn = testHistogram.value(); +// MixedObject - number | undefined +const valueFnMixedObject_NumberOrUndefined: valueAccessor = histoMixed_NumberOrUndefined.value(); +histoMixed_NumberOrUndefined = histoMixed_NumberOrUndefined.value((d: MixedObject, i: number, data: ArrayLike) => { + return d.str === "NA" ? undefined : d.num; +}); + +// MixedObject | undefined - number | undefined +const valueFnMixedOrUndefined_NumberOrUndefined: valueAccessor = histoMixedOrUndefined_NumberOrUndefined.value(); +histoMixedOrUndefined_NumberOrUndefined = histoMixedOrUndefined_NumberOrUndefined.value((d: MixedObject | undefined, i: number, data: ArrayLike) => { + return d ? d.num : undefined; +}); + +// MixedObject | undefined - number +const valueFnMixedOrUndefined_Number: valueAccessor = histoMixedOrUndefined_Number.value(); +histoMixedOrUndefined_Number = histoMixedOrUndefined_Number.value((d: MixedObject | undefined, i: number, data: ArrayLike) => { + return d ? d.num : 0; +}); + +// MixedObject - Date +const valueFnMixedObject_Date: valueAccessor = histoMixedObject_Date.value(); +histoMixedObject_Date = histoMixedObject_Date.value((d: MixedObject, i: number, data: ArrayLike) => { + return d.date; +}); + +// MixedObject - Date | undefined +const valueFnMixedObject_DateOrUndefined: valueAccessor = histoMixedObject_DateOrUndefined.value(); +histoMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined.value((d: MixedObject, i: number, data: ArrayLike) => { + return d.date; +}); // domain(...) ----------------------------------------------------------------- -// test with array -testHistogram = testHistogram.domain([new Date(2014, 3, 15), new Date(2017, 4, 15)]); +const domain = timeScale.domain(); +let domainFnNumber: (array: number[]) => [number, number] | [undefined, undefined]; +let domainFnNumberOrUndef: (array: Array) => [number, number] | [undefined, undefined]; +let domainFnDate: (values: Date[]) => [Date, Date]; -// usage with scale domain: -const domain = tScale.domain(); +// number - number +domainFnNumber = histoNumber_Number.domain(); +histoNumber_Number = histoNumber_Number.domain([0, 100]); +histoNumber_Number = histoNumber_Number.domain(d3Array.extent); -testHistogram = testHistogram.domain([domain[0], domain[domain.length]]); +// MixedObject - number | undefined +domainFnNumber = histoNumber_Number.domain(); +histoMixed_NumberOrUndefined = histoMixed_NumberOrUndefined.domain([0, 100]); +histoMixed_NumberOrUndefined = histoMixed_NumberOrUndefined.domain(d3Array.extent); -// testHistogram = testHistogram.domain(tScale.domain()); // fails, as scale domain is an array with possibly more than the two elements expected by histogram +// MixedObject | undefined - number | undefined +domainFnNumberOrUndef = histoMixedOrUndefined_NumberOrUndefined.domain(); +histoMixedOrUndefined_NumberOrUndefined = histoMixedOrUndefined_NumberOrUndefined.domain([0, 100]); +histoMixedOrUndefined_NumberOrUndefined = histoMixedOrUndefined_NumberOrUndefined.domain(d3Array.extent); -// use with accessor function -testHistogram = testHistogram.domain(values => [values[0], values[values.length]]); +// MixedObject | undefined - number +domainFnNumber = histoMixedOrUndefined_Number.domain(); +histoMixedOrUndefined_Number = histoMixedOrUndefined_Number.domain([0, 100]); +histoMixedOrUndefined_Number = histoMixedOrUndefined_Number.domain(d3Array.extent); -// get current domain accessor function -let domainAccessorFn: (values: Date[]) => [Date, Date]; -domainAccessorFn = testHistogram.domain(); +// MixedObject - Date +domainFnDate = histoMixedObject_Date.domain(); +histoMixedObject_Date = histoMixedObject_Date.domain([new Date(2014, 3, 15), new Date(2017, 4, 15)]); +histoMixedObject_Date = histoMixedObject_Date.domain([domain[0], domain[domain.length]]); +histoMixedObject_Date = histoMixedObject_Date.domain((values) => [values[0], values[values.length]]); +// $ExpectError +histoMixedObject_Date = histoMixedObject_Date.domain(timeScale.domain()); // fails, as scale domain is an array with possibly more than the two elements expected by histogram + +// MixedObject - Date | undefined +domainFnDate = histoMixedObject_Date.domain(); +histoMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined.domain([new Date(2014, 3, 15), new Date(2017, 4, 15)]); +histoMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined.domain([domain[0], domain[domain.length]]); +histoMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined.domain((values) => [values[0]!, values[values.length]!]); // thresholds(...) ------------------------------------------------------------- -// with count constant -defaultHistogram = defaultHistogram.thresholds(3); +type thresholdsWithUndefinedCont = d3Array.ThresholdCountGenerator; +type thresholdsWithUndefinedArray = d3Array.ThresholdNumberArrayGenerator; -// with threshold count generator -defaultHistogram = defaultHistogram.thresholds(d3Array.thresholdScott); +let thresholds: d3Array.ThresholdCountGenerator | d3Array.ThresholdNumberArrayGenerator; +let thresholdsWithUndefined: thresholdsWithUndefinedCont | thresholdsWithUndefinedArray; +const thresholdsArray: d3Array.ThresholdNumberArrayGenerator = (x: ArrayLike) => [5, 10, 20]; -// with thresholds value array +let thresholdsDate: d3Array.ThresholdDateArrayGenerator; +let thresholdsDateOrUndefined: d3Array.ThresholdDateArrayGenerator; -testHistogram = testHistogram.thresholds([new Date(2015, 11, 15), new Date(2016, 6, 1), new Date(2016, 8, 30)]); +// number - number +thresholds = histoNumber_Number.thresholds(); +histoNumber_Number = histoNumber_Number.thresholds(3); +histoNumber_Number = histoNumber_Number.thresholds([5, 10, 20]); +histoNumber_Number = histoNumber_Number.thresholds(d3Array.thresholdScott); +histoNumber_Number = histoNumber_Number.thresholds(thresholdsArray); -// with thresholds value array accessors -testHistogram = testHistogram.thresholds((values: Date[], min: Date, max: Date) => { - let thresholds: Date[]; - thresholds = [values[0], values[2], values[4]]; +// MixedObject - number | undefined +thresholdsWithUndefined = histoMixed_NumberOrUndefined.thresholds(); +histoMixed_NumberOrUndefined = histoMixed_NumberOrUndefined.thresholds(3); +histoMixed_NumberOrUndefined = histoMixed_NumberOrUndefined.thresholds([5, 10, 20]); +histoMixed_NumberOrUndefined = histoMixed_NumberOrUndefined.thresholds(d3Array.thresholdScott); + +// MixedObject | undefined - number | undefined +thresholdsWithUndefined = histoMixedOrUndefined_NumberOrUndefined.thresholds(); +histoMixedOrUndefined_NumberOrUndefined = histoMixedOrUndefined_NumberOrUndefined.thresholds(3); +histoMixedOrUndefined_NumberOrUndefined = histoMixedOrUndefined_NumberOrUndefined.thresholds([5, 10, 20]); +histoMixedOrUndefined_NumberOrUndefined = histoMixedOrUndefined_NumberOrUndefined.thresholds(d3Array.thresholdScott); + +// MixedObject | undefined - number +thresholds = histoMixedOrUndefined_Number.thresholds(); +histoMixedOrUndefined_Number = histoMixedOrUndefined_Number.thresholds(5); +histoMixedOrUndefined_Number = histoMixedOrUndefined_Number.thresholds([5, 10, 20]); +histoMixedOrUndefined_Number = histoMixedOrUndefined_Number.thresholds(d3Array.thresholdSturges); + +// MixedObject - Date +thresholdsDate = histoMixedObject_Date.thresholds(); +histoMixedObject_Date = histoMixedObject_Date.thresholds([new Date(2015, 11, 15), new Date(2016, 6, 1), new Date(2016, 8, 30)]); +histoMixedObject_Date = histoMixedObject_Date.thresholds(timeScale.ticks(timeYear)); +histoMixedObject_Date = histoMixedObject_Date.thresholds((values: ArrayLike) => [new Date(2015, 11, 15), new Date(2016, 6, 1), new Date(2016, 8, 30)]); +histoMixedObject_Date = histoMixedObject_Date.thresholds((values: ArrayLike, min: Date, max: Date) => { + const thresholds: Date[] = [values[0], values[2], values[4]]; + return thresholds; +}); +// $ExpectError +histoMixedObject_Date = histoMixedObject_Date.thresholds(d3Array.thresholdScott); + +// MixedObject - Date | undefined +thresholdsDateOrUndefined = histoMixedObject_DateOrUndefined.thresholds(); +histoMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined.thresholds([new Date(2015, 11, 15), new Date(2016, 6, 1), new Date(2016, 8, 30)]); +histoMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined.thresholds(timeScale.ticks(timeYear)); +histoMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined.thresholds((values: ArrayLike, min: Date, max: Date) => { + const thresholds: Date[] = [values[0]!, new Date(2015, 11, 15), values[values.length]!]; return thresholds; }); -testHistogram = testHistogram.thresholds(tScale.ticks(timeYear)); - // Use histogram generator ===================================================== -numbersArray = [-1, 0, 1, 1, 3, 20, 234]; +undef = d3Array.histogram()([])[0].x0 as undefined; +undef = d3Array.histogram()([undefined])[0].x0 as undefined; -let defaultBins: Array>; -defaultBins = defaultHistogram(numbersArray); +// number - number +let binsNumber_Number: Array>; +binsNumber_Number = histoNumber_Number([-1, 0, 1, 1, 3, 20, 234]); -let defaultBin: d3Array.Bin; -defaultBin = defaultBins[0]; +let binNumber_Number: d3Array.Bin; +binNumber_Number = binsNumber_Number[0]; -num = defaultBin.length; // defaultBin is array -num = defaultBin[0]; // with element type number -num = defaultBin.x0; // bin lower bound is number -num = defaultBin.x1; // bin upper bound is number +num = binNumber_Number.length; +num = binNumber_Number[0]; +numOrUndefined = binNumber_Number.x0; +numOrUndefined = binNumber_Number.x1; -let testBins: Array>; -testBins = testHistogram(mixedObjectArray); -testBins = testHistogram(readonlyMixedObjectArray); +// MixedObject - number | undefined +let binsNumberMixed_NumberOrUndefined: Array>; +binsNumberMixed_NumberOrUndefined = histoMixed_NumberOrUndefined(mixedObjectArray); -let testBin: d3Array.Bin; -testBin = testBins[0]; +let binNumberMixed_NumberOrUndefined: d3Array.Bin; +binNumberMixed_NumberOrUndefined = binsNumberMixed_NumberOrUndefined[0]; -num = testBin.length; // defaultBin is array -const mixedObject: MixedObject = testBin[0]; // with element type MixedObject -date = testBin.x0; // bin lower bound is Date -date = testBin.x1; // bin upper bound is Date +num = binNumberMixed_NumberOrUndefined.length; +mixedObject = binNumberMixed_NumberOrUndefined[0]; +numOrUndefined = binNumberMixed_NumberOrUndefined.x0; +numOrUndefined = binNumberMixed_NumberOrUndefined.x1; + +// MixedObject | undefined - number | undefined +let binsNumberMixedOrUndefined_NumberOrUndefined: Array>; +binsNumberMixedOrUndefined_NumberOrUndefined = histoMixedOrUndefined_NumberOrUndefined(mixedObjectArray); + +let binNumberMixedOrUndefined_NumberOrUndefined: d3Array.Bin; +binNumberMixedOrUndefined_NumberOrUndefined = binsNumberMixedOrUndefined_NumberOrUndefined[0]; + +num = binNumberMixedOrUndefined_NumberOrUndefined.length; +mixedObjectOrUndefined = binNumberMixedOrUndefined_NumberOrUndefined[0]; +numOrUndefined = binNumberMixedOrUndefined_NumberOrUndefined.x0; +numOrUndefined = binNumberMixedOrUndefined_NumberOrUndefined.x1; + +// MixedObject | undefined - number +let binsNumberMixedOrUndefined_Number: Array>; +binsNumberMixedOrUndefined_Number = histoMixedOrUndefined_Number(mixedObjectArray); + +let binNumberMixedOrUndefined_Number: d3Array.Bin; +binNumberMixedOrUndefined_Number = binsNumberMixedOrUndefined_Number[0]; + +num = binNumberMixedOrUndefined_Number.length; +mixedObjectOrUndefined = binNumberMixedOrUndefined_Number[0]; +numOrUndefined = binNumberMixedOrUndefined_Number.x0; +numOrUndefined = binNumberMixedOrUndefined_Number.x1; + +// MixedObject - Date +let binsMixedObject_Date: Array>; +binsMixedObject_Date = histoMixedObject_Date(mixedObjectArray); +binsMixedObject_Date = histoMixedObject_Date(readonlyMixedObjectArray); + +let binMixedObject_Date: d3Array.Bin; +binMixedObject_Date = binsMixedObject_Date[0]; + +num = binMixedObject_Date.length; +mixedObject = binMixedObject_Date[0]; +dateOrUndefined = binMixedObject_Date.x0; +dateOrUndefined = binMixedObject_Date.x1; + +// MixedObject - Date | undefined +let binsMixedObject_DateOrUndefined: Array>; +binsMixedObject_DateOrUndefined = histoMixedObject_DateOrUndefined(mixedObjectArray); + +let binMixedObject_DateOrUndefined: d3Array.Bin; +binMixedObject_DateOrUndefined = binsMixedObject_DateOrUndefined[0]; + +num = binMixedObject_DateOrUndefined.length; +mixedObject = binMixedObject_DateOrUndefined[0]; +dateOrUndefined = binMixedObject_DateOrUndefined.x0; +dateOrUndefined = binMixedObject_DateOrUndefined.x1; // Histogram Tresholds ========================================================= @@ -716,3 +930,8 @@ num = d3Array.thresholdScott(readonlyNumbersArray, -1, 234); num = d3Array.thresholdSturges(numbersArray); num = d3Array.thresholdSturges(typedArray); num = d3Array.thresholdSturges(readonlyNumbersArray); + +// Deprecated ================================================================== + +const histDeprecatedNumber: d3Array.HistogramGenerator = d3Array.histogram(); +const histDeprecatedDate: d3Array.HistogramGenerator = d3Array.histogram(); diff --git a/types/d3-array/index.d.ts b/types/d3-array/index.d.ts index a42f8e1fe9..45bd86a704 100644 --- a/types/d3-array/index.d.ts +++ b/types/d3-array/index.d.ts @@ -1,10 +1,13 @@ // Type definitions for D3JS d3-array module 1.2 // Project: https://github.com/d3/d3-array -// Definitions by: Alex Ford , Boris Yankov , Tom Wanzek +// Definitions by: Alex Ford +// Boris Yankov +// Tom Wanzek +// denisname // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.3 -// Last module patch version validated against: 1.2.0 +// Last module patch version validated against: 1.2.1 // -------------------------------------------------------------------------- // Shared Types and Interfaces @@ -90,18 +93,27 @@ export function extent(array: ArrayLike, accessor: (dat * Return the mean of an array of numbers */ export function mean(array: ArrayLike): number | undefined; + +/** + * Return the mean of an array of numbers + */ export function mean(array: ArrayLike, accessor: (datum: T, index: number, array: ArrayLike) => number | undefined | null): number | undefined; /** * Return the median of an array of numbers */ export function median(array: ArrayLike): number | undefined; + +/** + * Return the median of an array of numbers + */ export function median(array: ArrayLike, accessor: (element: T, i: number, array: ArrayLike) => number | undefined | null): number | undefined; /** * Returns the p-quantile of an array of numbers */ export function quantile(array: ArrayLike, p: number): number | undefined; + export function quantile(array: ArrayLike, p: number, accessor: (element: T, i: number, array: ArrayLike) => number | undefined | null): number | undefined; /** @@ -312,29 +324,97 @@ export function zip(...arrays: Array>): T[][]; // Histogram // -------------------------------------------------------------------------------------- -export interface Bin extends Array { - x0: Value; - x1: Value; +export interface Bin extends Array { + x0: Value | undefined; + x1: Value | undefined; } /** * Type definition for threshold generator which returns the count of recommended thresholds */ -export type ThresholdCountGenerator = (values: ArrayLike, min?: number, max?: number) => number; +export type ThresholdCountGenerator = + (values: ArrayLike, min: number, max: number) => number; /** - * Type definition for threshold generator which returns an array of recommended thresholds + * Type definition for threshold generator which returns an array of recommended numbers thresholds */ -export type ThresholdArrayGenerator = (values: ArrayLike, min?: Value, max?: Value) => Value[]; +export type ThresholdNumberArrayGenerator = + (values: ArrayLike, min: number, max: number) => Value[]; -export interface HistogramGenerator { +/** + * Type definition for threshold generator which returns an array of recommended dates thresholds + */ +export type ThresholdDateArrayGenerator = + (values: ArrayLike, min: Date, max: Date) => Value[]; + +/** + * @deprecated Use `HistogramGeneratorNumber` for `number` values and `HistogramGeneratorDate for `Date` values. + */ +export interface HistogramGenerator { (data: ArrayLike): Array>; + value(): (d: Datum, i: number, data: ArrayLike) => Value; value(valueAccessor: (d: Datum, i: number, data: ArrayLike) => Value): this; - domain(): (values: ArrayLike) => [Value, Value]; + + domain(): (values: ArrayLike) => [Value, Value] | [undefined, undefined]; domain(domain: [Value, Value]): this; - domain(domainAccessor: (values: ArrayLike) => [Value, Value]): this; - thresholds(): ThresholdCountGenerator | ThresholdArrayGenerator; + domain(domainAccessor: (values: ArrayLike) => [Value, Value] | [undefined, undefined]): this; + + /** + * Set the array of values to be used as thresholds in determining the bins. + * + * Any threshold values outside the domain are ignored. The first bin.x0 is always equal to the minimum domain value, + * and the last bin.x1 is always equal to the maximum domain value. + * + * @param thresholds Array of threshold values used for binning. The elements must + * be of the same type as the materialized values of the histogram. + */ + thresholds(thresholds: ArrayLike): this; +} + +export interface HistogramCommon { + (data: ArrayLike): Array>; + + value(): (d: Datum, i: number, data: ArrayLike) => Value; + value(valueAccessor: (d: Datum, i: number, data: ArrayLike) => Value): this; +} + +export interface HistogramGeneratorDate extends HistogramCommon { + domain(): (values: ArrayLike) => [Date, Date]; + domain(domain: [Date, Date]): this; + domain(domainAccessor: (values: ArrayLike) => [Date, Date]): this; + + thresholds(): ThresholdDateArrayGenerator; + /** + * Set the array of values to be used as thresholds in determining the bins. + * + * Any threshold values outside the domain are ignored. The first bin.x0 is always equal to the minimum domain value, + * and the last bin.x1 is always equal to the maximum domain value. + * + * @param thresholds Array of threshold values used for binning. The elements must + * be of the same type as the materialized values of the histogram. + */ + thresholds(thresholds: ArrayLike): this; + /** + * Set a threshold accessor function, which returns the array of values to be used as + * thresholds in determining the bins. + * + * Any threshold values outside the domain are ignored. The first bin.x0 is always equal to the minimum domain value, + * and the last bin.x1 is always equal to the maximum domain value. + * + * @param thresholds A function which accepts as arguments the array of materialized values, and + * optionally the domain minimum and maximum. The function calcutates and returns the array of values to be used as + * thresholds in determining the bins. + */ + thresholds(thresholds: ThresholdDateArrayGenerator): this; +} + +export interface HistogramGeneratorNumber extends HistogramCommon { + domain(): (values: ArrayLike) => [number, number] | [undefined, undefined]; + domain(domain: [number, number]): this; + domain(domainAccessor: (values: ArrayLike) => [number, number] | [undefined, undefined]): this; + + thresholds(): ThresholdCountGenerator | ThresholdNumberArrayGenerator; /** * Divide the domain uniformly into approximately count bins. IMPORTANT: This threshold * setting approach only works, when the materialized values are numbers! @@ -357,7 +437,7 @@ export interface HistogramGenerator { * optionally the domain minimum and maximum. The function calcutates and returns the suggested * number of bins. */ - thresholds(count: ThresholdCountGenerator): this; + thresholds(count: ThresholdCountGenerator): this; /** * Set the array of values to be used as thresholds in determining the bins. * @@ -379,18 +459,25 @@ export interface HistogramGenerator { * optionally the domain minimum and maximum. The function calcutates and returns the array of values to be used as * thresholds in determining the bins. */ - thresholds(thresholds: ThresholdArrayGenerator): this; + thresholds(thresholds: ThresholdNumberArrayGenerator): this; } -export function histogram(): HistogramGenerator; -export function histogram(): HistogramGenerator; +export function histogram(): HistogramGeneratorNumber; +export function histogram(): HistogramGeneratorNumber; +export function histogram(): HistogramGeneratorDate; + +/** + * @deprecated Do not use Value generic which mixes number and Date types. Use either number or Date + * (in combination with undefined, as applicable) to obtain a type-specific histogram generator. + */ +export function histogram(): HistogramGenerator; // -------------------------------------------------------------------------------------- // Histogram Thresholds // -------------------------------------------------------------------------------------- -export function thresholdFreedmanDiaconis(values: ArrayLike, min: number, max: number): number; // of type ThresholdCountGenerator +export function thresholdFreedmanDiaconis(values: ArrayLike, min: number, max: number): number; // of type ThresholdCountGenerator -export function thresholdScott(values: ArrayLike, min: number, max: number): number; // of type ThresholdCountGenerator +export function thresholdScott(values: ArrayLike, min: number, max: number): number; // of type ThresholdCountGenerator -export function thresholdSturges(values: ArrayLike): number; // of type ThresholdCountGenerator +export function thresholdSturges(values: ArrayLike): number; // of type ThresholdCountGenerator diff --git a/types/d3-array/tsconfig.json b/types/d3-array/tsconfig.json index a1dbb238ee..3c940b388e 100644 --- a/types/d3-array/tsconfig.json +++ b/types/d3-array/tsconfig.json @@ -8,7 +8,7 @@ "noImplicitAny": true, "noImplicitThis": true, "strictNullChecks": true, - "strictFunctionTypes": false, + "strictFunctionTypes": true, "baseUrl": "../", "typeRoots": [ "../" diff --git a/types/d3-contour/d3-contour-tests.ts b/types/d3-contour/d3-contour-tests.ts index 4563521751..0184979be0 100644 --- a/types/d3-contour/d3-contour-tests.ts +++ b/types/d3-contour/d3-contour-tests.ts @@ -10,7 +10,7 @@ import * as d3Contour from 'd3-contour'; import { range, thresholdSturges, - ThresholdArrayGenerator, + ThresholdNumberArrayGenerator, ThresholdCountGenerator } from 'd3-array'; import { geoPath } from 'd3-geo'; @@ -39,13 +39,13 @@ function goldsteinPrice(x: number, y: number) { let size: [number, number]; let boolFlag: boolean; -const thresholdArrayGen: ThresholdArrayGenerator = (values: ArrayLike, min?: number, max?: number) => { +const thresholdArrayGen: ThresholdNumberArrayGenerator = (values: ArrayLike, min?: number, max?: number) => { let thresholds: number[]; thresholds = [values[1], values[2], values[4]]; return thresholds; }; -let thresholdGenerator: ThresholdArrayGenerator | ThresholdCountGenerator; +let thresholdGenerator: ThresholdNumberArrayGenerator | ThresholdCountGenerator; let pathStringMaybe: string | null; let num: number; diff --git a/types/d3-contour/index.d.ts b/types/d3-contour/index.d.ts index c0b3d70b5e..8d42275ee2 100644 --- a/types/d3-contour/index.d.ts +++ b/types/d3-contour/index.d.ts @@ -7,7 +7,7 @@ // Last module patch version validated against: 1.2.0 import { MultiPolygon } from 'geojson'; -import { ThresholdArrayGenerator, ThresholdCountGenerator } from 'd3-array'; +import { ThresholdNumberArrayGenerator, ThresholdCountGenerator } from 'd3-array'; /** * An extended GeoJSON MultiPolygon representing a contour. @@ -78,7 +78,7 @@ export interface Contours { /** * Returns the current threshold generator, which by default implements Sturges’ formula. */ - thresholds(): ThresholdCountGenerator | ThresholdArrayGenerator; + thresholds(): ThresholdCountGenerator | ThresholdNumberArrayGenerator; /** * Sets the threshold generator to use the specified count and returns this contour generator. * The input values’ extent will be uniformly divided into approximately count bins. @@ -110,7 +110,7 @@ export interface Contours { * @param thresholds A threshold generator function. The threshold generator function is passed the array of input values * as its argument and returns either an array of calculated thresholds, or the count of thresholds to use. */ - thresholds(thresholds: ThresholdCountGenerator | ThresholdArrayGenerator): this; + thresholds(thresholds: ThresholdCountGenerator | ThresholdNumberArrayGenerator): this; } /** @@ -196,7 +196,7 @@ export interface ContourDensity { /** * Returns the current threshold generator, which by default generates about twenty nicely-rounded density thresholds. */ - thresholds(): ThresholdCountGenerator | ThresholdArrayGenerator; + thresholds(): ThresholdCountGenerator | ThresholdNumberArrayGenerator; /** * Sets the threshold generator to use the specified count and returns this density contour estimator. * Approximately count uniformly-spaced nicely-rounded thresholds will be generated. @@ -228,7 +228,7 @@ export interface ContourDensity { * @param thresholds A threshold generator function. The threshold generator function is passed the array of input values * as its argument and returns either an array of calculated thresholds, or the count of thresholds to use. */ - thresholds(thresholds: ThresholdCountGenerator | ThresholdArrayGenerator): this; + thresholds(thresholds: ThresholdCountGenerator | ThresholdNumberArrayGenerator): this; /** * Returns the current bandwidth, which defaults to 20.4939….