11/* eslint-disable @typescript-eslint/no-explicit-any */
2- import type { ArrayType , Value , DataArray , Datum , index , Data , Series , ValueArray } from "./data.js" ;
2+ import type {
3+ ArrayType ,
4+ Value ,
5+ DataArray ,
6+ Datum ,
7+ index ,
8+ Data ,
9+ Series ,
10+ ValueArray ,
11+ TypedArray ,
12+ TypedArrayConstructor
13+ } from "./data.js" ;
314import { parse as isoParse } from "isoformat" ;
4- import { color , descending , quantile , TypedArray } from "d3" ;
15+ import { color , descending , quantile } from "d3" ;
516
617// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
718const TypedArray = Object . getPrototypeOf ( Uint8Array ) ;
@@ -50,17 +61,25 @@ export function valueof(
5061 value : ValueAccessor ,
5162 arrayType ?: ArrayType
5263) : ValueArray | Float32Array | Float64Array | null | undefined {
53- return data == null
54- ? data
55- : typeof value === "string"
56- ? map ( data , field ( value ) , arrayType )
57- : typeof value === "function"
58- ? map ( data , value , arrayType )
59- : typeof value === "number" || value instanceof Date || typeof value === "boolean"
60- ? map ( data , constant ( value ) , arrayType )
61- : value && typeof ( value as TransformMethod ) . transform === "function"
62- ? arrayify ( ( value as TransformMethod ) . transform ( data ) , arrayType )
63- : arrayify ( value as ValueArray , arrayType ) ; // preserve undefined type
64+ if ( value == null ) return value ;
65+ if ( isTransform ( value ) ) {
66+ data = value . transform ( data ) as Data | null | undefined ;
67+ value = ( d ) => d as Value ;
68+ }
69+ if ( data == null ) {
70+ return data ;
71+ } else if ( typeof value === "string" ) {
72+ return map ( data , field ( value ) , arrayType ) ;
73+ } else if ( typeof value === "function" ) {
74+ return map ( data , value , arrayType ) ;
75+ } else if ( typeof value === "number" || value instanceof Date || typeof value === "boolean" ) {
76+ return map ( data , constant ( value ) , arrayType ) ;
77+ }
78+ return arrayify ( value , arrayType ) ; // preserve undefined type
79+ }
80+
81+ function isTransform ( value : ValueAccessor ) : value is TransformMethod {
82+ return ! ! value && isObject ( value ) && typeof ( value as { transform ?: any } ) . transform == "function" ;
6483}
6584
6685/**
@@ -76,9 +95,9 @@ export type ValueAccessor =
7695 | ValueArray
7796 | null
7897 | undefined ;
79- type AccessorFunction = ( ( d : any ) => V ) | ( ( d : any , i : number ) => V ) ;
98+ type AccessorFunction = ( ( d : Datum ) => Value ) & ( ( d : Datum , i : number ) => Value ) ;
8099type TransformMethod = {
81- transform : ( data : Data | null | undefined ) => Data ;
100+ transform : ( data : Data | null | undefined ) => ArrayLike < Value > | Iterable < Value > | null | undefined ;
82101} ;
83102
84103// Type: the field accessor might crash if the datum is not a generic object
@@ -120,9 +139,13 @@ export function percentile(reduce: percentile) {
120139// tuple [channel, constant] where one of the two is undefined, and the other is
121140// the given value. If you wish to reference a named field that is also a valid
122141// CSS color, use an accessor (d => d.red) instead.
123- export function maybeColorChannel ( value : ValueAccessor , defaultValue ?: string ) : [ ValueAccessor ?, string ?] {
142+ export function maybeColorChannel ( value : string | ValueAccessor , defaultValue ?: string ) : [ ValueAccessor ?, string ?] {
124143 if ( value === undefined ) value = defaultValue ;
125- return value === null ? [ undefined , "none" ] : isColor ( value ) ? [ undefined , value as string ] : [ value , undefined ] ;
144+ return value === null
145+ ? [ undefined , "none" ]
146+ : isColor ( value as string )
147+ ? [ undefined , value as string ]
148+ : [ value as ValueAccessor , undefined ] ;
126149}
127150
128151// Similar to maybeColorChannel, this tests whether the given value is a number
@@ -148,26 +171,28 @@ export function keyword(input: string | null | undefined, name: string, allowed:
148171// type is provided (e.g., Array), then the returned array will strictly be of
149172// the specified type; otherwise, any array or typed array may be returned. If
150173// the specified data is null or undefined, returns the value as-is.
151- export function arrayify ( data : undefined , type : ArrayType | undefined ) : undefined ;
152- export function arrayify ( data : null , type : ArrayType | undefined ) : null ;
153- export function arrayify ( data : Data ) : Array < Datum > | TypedArray ;
154- export function arrayify ( data : Data , type : ArrayConstructor ) : Array < Datum > ;
155- export function arrayify ( data : Data , type : Float32ArrayConstructor ) : Float32Array ;
156- export function arrayify ( data : Data , type : Float64ArrayConstructor ) : Float64Array ;
157- export function arrayify ( data : Data , type ?: ArrayType ) : Array < Datum > | Float32Array | Float64Array ;
158- export function arrayify ( data : Data | null | undefined ) : Array < Datum > | TypedArray | null | undefined ;
159- export function arrayify ( data : Data | null | undefined , type : ArrayConstructor ) : Array < Datum > | null | undefined ;
160- export function arrayify ( data : Data | null | undefined , type : Float32ArrayConstructor ) : Float32Array | null | undefined ;
161- export function arrayify ( data : Data | null | undefined , type : Float64ArrayConstructor ) : Float64Array | null | undefined ;
162- export function arrayify (
163- data : Data | null | undefined ,
164- type ?: ArrayType
165- ) : TypedArray | Array < Datum > | null | undefined {
174+ export function arrayify < N extends null | undefined > ( data : N , type : ArrayType | undefined ) : N ;
175+ export function arrayify < N extends null | undefined | TypedArray > ( data : N ) : N ;
176+ export function arrayify < N extends null | undefined | TypedArray > ( data : N , type : undefined ) : N ;
177+ export function arrayify ( data : TypedArray , type : TypedArrayConstructor | undefined ) : TypedArray ;
178+ export function arrayify ( data : Value [ ] | Iterable < Value > , type : ArrayConstructor | undefined ) : Value [ ] ;
179+ export function arrayify ( data : ValueArray | Iterable < Value > ) : ValueArray ;
180+ export function arrayify ( data : ValueArray | Iterable < Value > , type : ArrayConstructor | undefined ) : ValueArray ;
181+ export function arrayify ( data : ValueArray | Iterable < Value > , type : TypedArrayConstructor ) : TypedArray ;
182+ export function arrayify ( data : ValueArray , type : ArrayType | undefined ) : ValueArray ;
183+ export function arrayify ( data : Data , type ?: ArrayType ) : DataArray | TypedArray ;
184+ export function arrayify ( data : Data ) : DataArray ;
185+ export function arrayify ( data : Data , type : ArrayConstructor ) : DataArray ;
186+ export function arrayify ( data : Data , type : TypedArrayConstructor ) : TypedArray ;
187+ export function arrayify ( data : Data , type ?: ArrayType ) : DataArray | TypedArray ;
188+ export function arrayify ( data : Data | null | undefined , type ?: ArrayType ) : DataArray | ValueArray | null | undefined {
166189 return data == null
167190 ? data
168191 : type === undefined
169- ? data instanceof Array || data instanceof TypedArray
170- ? ( data as ValueArray )
192+ ? data instanceof Array
193+ ? data
194+ : data instanceof TypedArray
195+ ? ( data as TypedArray )
171196 : Array . from ( data )
172197 : data instanceof type
173198 ? data
@@ -176,14 +201,47 @@ export function arrayify(
176201
177202// An optimization of type.from(values, f): if the given values are already an
178203// instanceof the desired array type, the faster values.map method is used.
179- type U = Data ;
180- type V = Value ;
181- export function map < V extends Value > ( values : U , f : ( d : any , i : number ) => V , type : ArrayConstructor ) : V [ ] ;
182- export function map ( values : U , f : ( d : any , i : number ) => number , type : Float32ArrayConstructor ) : Float32Array ;
183- export function map ( values : U , f : ( d : any , i : number ) => number , type : Float64ArrayConstructor ) : Float64Array ;
184- export function map ( values : U , f : AccessorFunction , type : ArrayType | undefined ) : V [ ] ;
185- export function map ( values : U , f : AccessorFunction ) : V [ ] ;
186- export function map ( values : U , f : ( d : any , i : number ) => any , type : ArrayType = Array ) {
204+ export function map ( index : Series , f : ( d : index , i : number ) => Value ) : ValueArray ;
205+ export function map ( values : ValueArray , f : ( d : Value , i : number ) => Value ) : ValueArray ;
206+ export function map (
207+ values : ValueArray ,
208+ f : ( d : any , i : number ) => Value ,
209+ type : ArrayConstructor | undefined
210+ ) : ValueArray ;
211+ export function map (
212+ values : ValueArray ,
213+ f : ( d : Value , i : number ) => number ,
214+ type : Float32ArrayConstructor
215+ ) : Float32Array ;
216+ export function map (
217+ values : ValueArray ,
218+ f : ( d : Value , i : number ) => number ,
219+ type : Float64ArrayConstructor
220+ ) : Float64Array ;
221+ export function map (
222+ values : ArrayLike < Value > | Iterable < Value > ,
223+ f : ( d : any , i : number ) => number ,
224+ type : Float32ArrayConstructor
225+ ) : Float32Array ;
226+ export function map (
227+ values : ArrayLike < Value > | Iterable < Value > ,
228+ f : ( d : any , i : number ) => number ,
229+ type : Float64ArrayConstructor
230+ ) : Float64Array ;
231+ export function map ( values : Data , f : AccessorFunction , type : ArrayType | undefined ) : Value [ ] ;
232+ export function map ( values : Data , f : AccessorFunction ) : Value [ ] ;
233+ export function map ( values : Data , f : ( d : any , i : number ) => any , type : ArrayType | undefined ) : Value [ ] ;
234+ export function map ( values : Data , f : ( d : any , i : number ) => Value , type : ArrayConstructor ) : Value [ ] ;
235+ export function map ( values : Data , f : ( d : any , i : number ) => number , type : Float32ArrayConstructor ) : Float32Array ;
236+ export function map ( values : Data , f : ( d : any , i : number ) => number , type : Float64ArrayConstructor ) : Float64Array ;
237+ export function map ( values : Data , f : AccessorFunction , type : ArrayType | undefined ) : Value [ ] ;
238+ export function map ( values : Data , f : AccessorFunction ) : Value [ ] ;
239+ export function map ( values : Data , f : ( d : any , i : number ) => any , type : ArrayType | undefined ) : Value [ ] ;
240+ export function map (
241+ values : Data | ArrayLike < Value > | Iterable < Value > ,
242+ f : ( d : any , i : number ) => any ,
243+ type : ArrayType = Array
244+ ) : ValueArray {
187245 return values instanceof type ? values . map ( f ) : ( type as ArrayConstructor ) . from ( values , f ) ;
188246}
189247
@@ -227,12 +285,12 @@ export function isDomainSort(sort: any): boolean {
227285}
228286
229287// For marks specified either as [0, x] or [x1, x2], such as areas and bars.
230- type Identity = { transform : ( d : Datum ) => Datum } ;
231- export function maybeZero (
288+ type Identity < T extends Datum > = { transform : ( d : T ) => T } ;
289+ export function maybeZero < T extends Datum > (
232290 x : ValueAccessor | undefined ,
233291 x1 : ValueAccessor | undefined | 0 ,
234- x2 : ValueAccessor | undefined | Identity | 0 ,
235- x3 = identity
292+ x2 : ValueAccessor | undefined | Identity < T > | 0 ,
293+ x3 = identity as Identity < T >
236294) {
237295 if ( x1 === undefined && x2 === undefined ) {
238296 // {x} or {}
@@ -256,7 +314,11 @@ export function maybeTuple<T>(x: T | undefined, y: T | undefined): [T | undefine
256314
257315// A helper for extracting the z channel, if it is variable. Used by transforms
258316// that require series, such as moving average and normalize.
259- type ZOptions = { fill ?: ValueAccessor ; stroke ?: ValueAccessor ; z ?: ValueAccessor } ;
317+ type ZOptions = {
318+ fill ?: ValueAccessor | string ;
319+ stroke ?: ValueAccessor | string ;
320+ z ?: ValueAccessor ;
321+ } ;
260322export function maybeZ ( { z, fill, stroke} : ZOptions = { } ) {
261323 if ( z === undefined ) [ z ] = maybeColorChannel ( fill ) ;
262324 if ( z === undefined ) [ z ] = maybeColorChannel ( stroke ) ;
@@ -333,8 +395,8 @@ export function maybeColumn(source: ValueAccessor | ((data: DataArray) => void))
333395export function labelof ( value : any , defaultValue ?: string ) {
334396 return typeof value === "string"
335397 ? value
336- : value && ( value as { label ? : string } ) . label !== undefined
337- ? ( value as { label ? : string } ) . label
398+ : value && ( value as { label : string } ) . label != null
399+ ? ( value as { label : string } ) . label
338400 : defaultValue ;
339401}
340402
@@ -348,8 +410,8 @@ export function mid(x1: getColumn, x2: getColumn) {
348410 const X1 = x1 . transform ( ) ;
349411 const X2 = x2 . transform ( ) ;
350412 return isTemporal ( X1 ) || isTemporal ( X2 )
351- ? map ( X1 , ( _ : Date , i : index ) => new Date ( ( + ( X1 [ i ] as number ) + + ( X2 [ i ] as number ) ) / 2 ) )
352- : map ( X1 , ( _ : Date , i : index ) => ( + ( X1 [ i ] as number ) + + ( X2 [ i ] as number ) ) / 2 , Float64Array ) ;
413+ ? map ( X1 , ( _ , i ) => new Date ( ( + ( X1 [ i ] as number ) + + ( X2 [ i ] as number ) ) / 2 ) )
414+ : map ( X1 , ( _ , i ) => ( + ( X1 [ i ] as number ) + + ( X2 [ i ] as number ) ) / 2 , Float64Array ) ;
353415 } ,
354416 label : x1 . label
355417 } ;
@@ -363,7 +425,7 @@ export function maybeValue(value: any) {
363425// Coerces the given channel values (if any) to numbers. This is useful when
364426// values will be interpolated into other code, such as an SVG transform, and
365427// where we don’t wish to allow unexpected behavior for weird input.
366- export function numberChannel ( source : ValueArray ) {
428+ export function numberChannel ( source : any ) {
367429 return source == null
368430 ? null
369431 : {
0 commit comments