88
99import * as d3Dispatch from "d3-dispatch" ;
1010
11+ // Utils --------------------------------------------
12+
13+ let extractTests : [
14+ // $ExpectType 'a'
15+ d3Dispatch . Dispatch . ExtractEventNames < "a" > ,
16+ // $ExpectType 'a'
17+ d3Dispatch . Dispatch . ExtractEventNames < "a.1" > ,
18+ // $ExpectType 'a' | 'b'
19+ d3Dispatch . Dispatch . ExtractEventNames < "a b" > ,
20+ // $ExpectType 'a' | 'b' | 'c'
21+ d3Dispatch . Dispatch . ExtractEventNames < "a b c" > ,
22+ // $ExpectType 'a' | 'b'
23+ d3Dispatch . Dispatch . ExtractEventNames < "a.1 b" > ,
24+ // $ExpectType 'a' | 'b'
25+ d3Dispatch . Dispatch . ExtractEventNames < "a.1 b.2" > ,
26+ // $ExpectType 'a' | 'b'
27+ d3Dispatch . Dispatch . ExtractEventNames < "a b.2" > ,
28+ // $ExpectType 'a'
29+ d3Dispatch . Dispatch . ExtractEventNames < "a " > ,
30+ // $ExpectType 'a'
31+ d3Dispatch . Dispatch . ExtractEventNames < " a" > ,
32+ // $ExpectType 'a'
33+ d3Dispatch . Dispatch . ExtractEventNames < " a " > ,
34+ // $ExpectType 'a' | 'b'
35+ d3Dispatch . Dispatch . ExtractEventNames < " a b " > ,
36+ ] ;
37+
1138// Preparation --------------------------------------------
1239
1340interface Datum {
@@ -19,24 +46,33 @@ interface ContextObject {
1946 about : string ;
2047}
2148
22- let dispatch : d3Dispatch . Dispatch < HTMLElement > ;
23- let dispatch2 : d3Dispatch . Dispatch < ContextObject > ;
2449let callback : ( this : HTMLElement , ...args : any [ ] ) => void ;
2550let callbackOrUndef : ( ( this : HTMLElement , ...args : any [ ] ) => void ) | undefined ;
2651let undef : undefined ;
2752
2853// Signature Tests ----------------------------------------
2954
3055// create new dispatch object
31- dispatch = d3Dispatch . dispatch ( "foo" , "bar" ) ;
32- dispatch2 = d3Dispatch . dispatch ( "start" , "end" ) ;
56+ const dispatch = d3Dispatch . dispatch < HTMLElement , {
57+ foo : [ d ?: Datum , i ?: number ] ;
58+ bar : [ ] ;
59+ } > ( "foo" , "bar" ) ;
60+
61+ // $ExpectType Dispatch<HTMLElement, { foo: [d?: Datum | undefined, i?: number | undefined]; bar: [] }>
62+ dispatch ;
63+
64+ // in this example, the type-arguments are inferred
65+ const dispatch2 = d3Dispatch . dispatch ( "start" , "end" ) ;
66+
67+ // $ExpectType Dispatch<object, Record<"start" | "end", any[]>>
68+ dispatch2 ;
3369
34- function cbFn ( this : HTMLElement , d : Datum , i : number ) {
70+ function cbFn ( this : HTMLElement , d ? : Datum , i ? : number ) {
3571 console . log ( this . baseURI ? this . baseURI : "nada" ) ;
3672 console . log ( d ? d . a : "nada" ) ;
3773}
3874
39- function cbFn2 ( this : SVGElement , d : Datum , i : number ) {
75+ function cbFn2 ( this : SVGElement , d ? : Datum , i ? : number ) {
4076 console . log ( this . baseURI ? this . baseURI : "nada" ) ;
4177 console . log ( d ? d . a : "nada" ) ;
4278}
@@ -45,6 +81,9 @@ dispatch.on("foo", cbFn);
4581// @ts -expect-error
4682dispatch . on ( "foo" , cbFn2 ) ; // test fails as 'this' context type is mismatched between dispatch and callback function
4783
84+ // @ts -expect-error -- test fails since there are 3 arguments, but only 2 in the defintion
85+ dispatch . on ( "foo" , ( a , b , c ) => { } ) ;
86+
4887callback = dispatch . on ( "bar" ) ! ;
4988callbackOrUndef = dispatch . on ( "bar" ) ;
5089callbackOrUndef = dispatch . on ( "unknown" ) ;
@@ -60,6 +99,8 @@ dispatch2.call("start", { about: "I am a context object" }, "I am an argument");
6099
61100dispatch . apply ( "bar" ) ;
62101dispatch . apply ( "bar" , document . body ) ;
102+ dispatch . apply ( "bar" , document . body , [ ] ) ;
103+ // @ts -expect-error -- `bar` expected 0 arguments
63104dispatch . apply ( "bar" , document . body , [ { a : 3 , b : "test" } , 1 ] ) ;
64105
65106dispatch . on ( "bar" , null ) ;
@@ -68,3 +109,166 @@ dispatch.on("bar", null);
68109const copy : d3Dispatch . Dispatch < HTMLElement > = dispatch . copy ( ) ;
69110// @ts -expect-error
70111const copy2 : d3Dispatch . Dispatch < SVGElement > = dispatch . copy ( ) ; // test fails type mismatch of underlying event target
112+
113+ const abc = d3Dispatch . dispatch ( "a" , "b" , "c" ) ;
114+ // valid cases:
115+ abc . on ( "a" , null ) ;
116+ abc . on ( "b" , null ) ;
117+ abc . on ( "a.1" , null ) ;
118+ abc . on ( "b.b" , null ) ;
119+ abc . on ( "a b" , null ) ;
120+ abc . on ( "a.1 b" , null ) ;
121+ abc . on ( "a.1 b.1" , null ) ;
122+ abc . on ( "a b.2" , null ) ;
123+ abc . on ( " a" , null ) ;
124+ abc . on ( "a " , null ) ;
125+ abc . call ( "a" ) ;
126+ abc . apply ( "a" ) ;
127+
128+ // invalid, but no error. the arguments are just `never`:
129+ abc . on ( " " , ( ...args ) => {
130+ // $ExpectType never
131+ args ;
132+ } ) ;
133+
134+ // invalid cases:
135+ // @ts -expect-error -- d isn't defined
136+ abc . on ( "d" , null ) ;
137+ // @ts -expect-error -- d isn't defined
138+ abc . on ( "d.a" , null ) ;
139+ // @ts -expect-error -- d isn't defined
140+ abc . on ( "d e" , null ) ;
141+ // @ts -expect-error -- d isn't defined
142+ abc . on ( "d e.a" , null ) ;
143+ // @ts -expect-error -- e isn't defined
144+ abc . on ( "a e c" , null ) ;
145+ // @ts -expect-error -- e isn't defined
146+ abc . on ( "a e c.1" , null ) ;
147+ // @ts -expect-error -- nothing before and after period
148+ abc . on ( "." , null ) ;
149+ // @ts -expect-error -- d isn't defined
150+ abc . call ( "d" ) ;
151+ // @ts -expect-error -- empty string
152+ abc . call ( "" ) ;
153+ // @ts -expect-error -- d isn't defined
154+ abc . apply ( "d" ) ;
155+ // @ts -expect-error -- empty string before period
156+ abc . on ( "a.2 b ." , null ) ;
157+ // @ts -expect-error -- empty string before period
158+ abc . on ( "a.2 b .3" , null ) ;
159+ // @ts -expect-error -- empty string
160+ abc . apply ( "" ) ;
161+
162+ // this one has no event map, but we still infer the event names
163+ // and validate if an invalid event is passed to .apply() or .call()
164+ const inferred = d3Dispatch . dispatch ( "a" , "b" , "c" ) ;
165+
166+ inferred . on ( "a" , ( ...args ) => {
167+ // $ExpectType any[]
168+ args ;
169+ } ) ;
170+ inferred . on ( "b" , ( ...args ) => {
171+ // $ExpectType any[]
172+ args ;
173+ } ) ;
174+ inferred . on ( "b.1" , ( ...args ) => {
175+ // $ExpectType any[]
176+ args ;
177+ } ) ;
178+ inferred . on ( "c" , ( ...args ) => {
179+ // $ExpectType any[]
180+ args ;
181+ } ) ;
182+ // @ts -expect-error -- event name is not defined
183+ inferred . on ( "invalid" , ( ) => { } ) ;
184+ inferred . on ( "a b" , ( ...args ) => {
185+ // $ExpectType any[]
186+ args ;
187+ } ) ;
188+ inferred . on ( "a.1 b.2" , ( ...args ) => {
189+ // $ExpectType any[]
190+ args ;
191+ } ) ;
192+ // @ts -expect-error -- e is not valid
193+ inferred . on ( "a.1 b.2 e" , ( ...args ) => { } ) ;
194+ inferred . call ( "a" ) ;
195+ inferred . call ( "a" , window ) ;
196+ inferred . call ( "a" , window , 1 , 2 ) ;
197+ inferred . apply ( "a" ) ;
198+ inferred . apply ( "a" , window , [ ] ) ;
199+ inferred . apply ( "a" , window , [ 1 , 2 ] ) ;
200+
201+ // @ts -expect-error -- event does not exist
202+ inferred . call ( "d" ) ;
203+ // @ts -expect-error -- event does not exist
204+ inferred . call ( "" ) ;
205+ // @ts -expect-error -- event does not exist
206+ inferred . apply ( "d" ) ;
207+ // @ts -expect-error -- event does not exist
208+ inferred . apply ( "" ) ;
209+
210+ interface EventMap {
211+ // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type -- intentional
212+ a : [ number ] ;
213+ b : [ ] ;
214+ c : [ string , boolean ] ;
215+ }
216+ const explicit = d3Dispatch . dispatch < ContextObject , EventMap > ( "a" , "b" , "c" ) ;
217+
218+ // @ts -expect-error -- type-arguments must match runtime-arguments
219+ d3Dispatch . dispatch < ContextObject , EventMap > ( "a" , "b" , "c" , "d" ) ;
220+ // @ts -expect-error -- type-arguments must match runtime-arguments
221+ d3Dispatch . dispatch < ContextObject , EventMap > ( "a" , "b" , "d" ) ;
222+
223+ explicit . on ( "a" , function ( ...args ) {
224+ // $ExpectType [number]
225+ args ;
226+ // $ExpectType ContextObject
227+ this ;
228+ } ) ;
229+ explicit . on ( "b" , ( ...args ) => {
230+ // $ExpectType []
231+ args ;
232+ } ) ;
233+ explicit . on ( "b.1" , ( ...args ) => {
234+ // $ExpectType []
235+ args ;
236+ } ) ;
237+ explicit . on ( "c" , ( ...args ) => {
238+ // $ExpectType [string, boolean]
239+ args ;
240+ } ) ;
241+ // @ts -expect-error -- event name is not defined
242+ explicit . on ( "invalid" , ( ) => { } ) ;
243+ explicit . on ( "a b" , ( ...args ) => {
244+ // union of `a` and `b`'s types
245+ // $ExpectType [number] | []
246+ args ;
247+ } ) ;
248+ explicit . on ( "a.1 b.2" , ( ...args ) => {
249+ // union of `a` and `b`'s types
250+ // $ExpectType [number] | []
251+ args ;
252+ } ) ;
253+ // @ts -expect-error -- e is not valid
254+ explicit . on ( "a.1 b.2 e" , ( ...args ) => { } ) ;
255+
256+ explicit . apply ( "a" , this , [ 123 ] ) ;
257+ explicit . apply ( "b" , this , [ ] ) ;
258+ explicit . apply ( "c" , this , [ "" , true ] ) ;
259+ // @ts -expect-error -- event does not exist
260+ inferred . apply ( "d" ) ;
261+ // @ts -expect-error -- invalid arguments
262+ explicit . apply ( "a" , this , [ ] ) ;
263+ // @ts -expect-error -- invalid arguments
264+ explicit . apply ( "b" , this , [ 1 ] ) ;
265+
266+ explicit . call ( "a" , this , 123 ) ;
267+ explicit . call ( "b" , this ) ;
268+ explicit . call ( "c" , this , "" , true ) ;
269+ // @ts -expect-error -- event does not exist
270+ inferred . call ( "d" ) ;
271+ // @ts -expect-error -- invalid arguments
272+ explicit . call ( "a" , this ) ;
273+ // @ts -expect-error -- invalid arguments
274+ explicit . call ( "b" , this , 1 ) ;
0 commit comments