-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from alexreardon/trying-new-types
new public Listener type
- Loading branch information
Showing
14 changed files
with
359 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,4 +12,6 @@ node_modules/ | |
dist/ | ||
|
||
# yarn | ||
yarn-error.log | ||
yarn-error.log | ||
|
||
.npmrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
12.18.0 | ||
16.15.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "bind-event-listener", | ||
"version": "2.0.0", | ||
"version": "2.1.0-beta.0", | ||
"private": false, | ||
"description": "Making binding and unbinding DOM events easier", | ||
"author": "Alex Reardon <[email protected]>", | ||
|
@@ -52,6 +52,7 @@ | |
"prettier": "^2.5.1", | ||
"rimraf": "^3.0.2", | ||
"size-limit": "^7.0.5", | ||
"ts-expect": "^1.3.0", | ||
"ts-jest": "^27.1.3", | ||
"typescript": "^4.6.4" | ||
}, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export { bind } from './bind'; | ||
export { bindAll } from './bind-all'; | ||
export { Binding, UnbindFn } from './types'; | ||
export { Binding, Listener, UnbindFn } from './types'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,37 @@ | ||
export type UnbindFn = () => void; | ||
|
||
type AnyFunction = (...args: any[]) => any; | ||
|
||
type GetEventType<Target extends EventTarget, Type extends string> = Target extends unknown | ||
? `on${Type}` extends keyof Target | ||
? GetEventTypeFromListener< | ||
// remove types that aren't assignable to `AnyFunction` | ||
// so that we don't end up with union like `MouseEvent | Event` | ||
Extract<Target[`on${Type}`], AnyFunction> | ||
> | ||
type ExtractEventTypeFromHandler<MaybeFn extends unknown> = MaybeFn extends ( | ||
this: any, | ||
event: infer MaybeEvent, | ||
) => any | ||
? MaybeEvent extends Event | ||
? MaybeEvent | ||
: Event | ||
: never; | ||
|
||
type GetEventTypeFromListener<T extends AnyFunction> = T extends (this: any, event: infer U) => any | ||
? U extends Event | ||
? U | ||
: Event | ||
// Given an EventTarget and an EventName - return the event type (eg `MouseEvent`) | ||
// Rather than switching on every time of EventTarget and looking up the appropriate `EventMap` | ||
// We are being sneaky an pulling the type out of any `on${EventName}` property | ||
// This is surprisingly robust | ||
type GetEventType< | ||
Target extends EventTarget, | ||
EventName extends string, | ||
> = `on${EventName}` extends keyof Target | ||
? ExtractEventTypeFromHandler<Target[`on${EventName}`]> | ||
: Event; | ||
|
||
export type Binding<Target extends EventTarget = EventTarget, Type extends string = string> = { | ||
type: Type; | ||
listener: Listener<GetEventType<Target, Type>, Target>; | ||
options?: boolean | AddEventListenerOptions; | ||
// For listener objects, the handleEvent function has the object as the `this` binding | ||
type ListenerObject<TEvent extends Event> = { | ||
handleEvent(this: ListenerObject<TEvent>, e: TEvent): void; | ||
}; | ||
|
||
export type Listener<Ev extends Event, Target extends EventTarget> = | ||
| ListenerObject<Ev> | ||
// For a listener function, the `this` binding is the target the event listener is added to | ||
// using bivariance hack here so if the user | ||
// wants to narrow event type by hand TS | ||
// won't give them an error | ||
| { bivarianceHack(this: Target, e: Ev): void }['bivarianceHack']; | ||
// event listeners can be an object or a function | ||
export type Listener<Target extends EventTarget, EventName extends string> = | ||
| ListenerObject<GetEventType<Target, EventName>> | ||
| { (this: Target, e: GetEventType<Target, EventName>): void }; | ||
|
||
type ListenerObject<Ev extends Event> = { | ||
// For listener objects, the handleEvent function has the object as the `this` binding | ||
handleEvent(this: ListenerObject<Ev>, Ee: Ev): void; | ||
export type Binding<Target extends EventTarget = EventTarget, EventName extends string = string> = { | ||
type: EventName; | ||
listener: Listener<Target, EventName>; | ||
options?: boolean | AddEventListenerOptions; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { bindAll } from '../../src'; | ||
|
||
// inline definitions | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
bindAll(button, [ | ||
{ | ||
type: 'click', | ||
listener(event: MouseEvent) {}, | ||
}, | ||
{ | ||
type: 'keydown', | ||
listener(event: KeyboardEvent) {}, | ||
}, | ||
]); | ||
} | ||
|
||
// inferred types | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
bindAll(button, [ | ||
{ | ||
type: 'click', | ||
listener(event: MouseEvent) { | ||
const value: number = event.button; | ||
}, | ||
}, | ||
{ | ||
type: 'keydown', | ||
listener(event: KeyboardEvent) { | ||
const value: string = event.key; | ||
}, | ||
}, | ||
]); | ||
} | ||
|
||
// hoisted definitions | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
function click(event: MouseEvent) {} | ||
function keydown(event: KeyboardEvent) {} | ||
|
||
bindAll(button, [ | ||
{ | ||
type: 'click', | ||
listener: click, | ||
}, | ||
{ | ||
type: 'keydown', | ||
listener: keydown, | ||
}, | ||
]); | ||
} | ||
|
||
// hoisted incorrect definitions | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
function listener(event: KeyboardEvent) {} | ||
|
||
bindAll(button, [ | ||
{ | ||
type: 'click', | ||
// @ts-expect-error | ||
listener: listener, | ||
}, | ||
]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { bind } from '../../src'; | ||
|
||
// inline definitions | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
bind(button, { | ||
type: 'click', | ||
listener(event: MouseEvent) {}, | ||
}); | ||
} | ||
|
||
// inferred types | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
bind(button, { | ||
type: 'click', | ||
listener(event) { | ||
const value: number = event.button; | ||
}, | ||
}); | ||
} | ||
|
||
// hoisted definitions | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
function listener(event: MouseEvent) {} | ||
|
||
bind(button, { | ||
type: 'click', | ||
listener: listener, | ||
}); | ||
} | ||
|
||
// hoisted incorrect definitions | ||
{ | ||
const button: HTMLElement = document.createElement('button'); | ||
|
||
function listener(event: KeyboardEvent) {} | ||
|
||
bind(button, { | ||
type: 'click', | ||
// @ts-expect-error | ||
listener: listener, | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.