[TS] Improve types and (#1043)

This commit is contained in:
filtered
2025-05-13 05:02:57 +10:00
committed by GitHub
parent 10118d95e3
commit de32560816
11 changed files with 160 additions and 52 deletions

View File

@@ -1,21 +1,84 @@
/** {@link Omit} all properties that evaluate to `never`. */
type NeverNever<T> = {
[K in keyof T as T[K] extends never ? never : K]: T[K]
}
/** {@link Pick} only properties that evaluate to `never`. */
type PickNevers<T> = {
[K in keyof T as T[K] extends never ? K : never]: T[K]
}
import type { NeverNever, PickNevers } from "@/types/utility"
type EventListeners<T> = {
readonly [K in keyof T]: ((this: EventTarget, ev: CustomEvent<T[K]>) => any) | EventListenerObject | null
}
/**
* Has strongly-typed overrides of {@link EventTarget.addEventListener} and {@link EventTarget.removeEventListener}.
*/
export interface ICustomEventTarget<
EventMap extends Record<Keys, unknown>,
Keys extends keyof EventMap & string = keyof EventMap & string,
> {
addEventListener<K extends Keys>(
type: K,
listener: EventListeners<EventMap>[K],
options?: boolean | AddEventListenerOptions,
): void
removeEventListener<K extends Keys>(
type: K,
listener: EventListeners<EventMap>[K],
options?: boolean | EventListenerOptions,
): void
/** @deprecated Use {@link dispatch}. */
dispatchEvent(event: never): boolean
}
/**
* Capable of dispatching strongly-typed events via {@link dispatch}.
* Overloads are used to ensure detail param is correctly optional.
*/
export interface CustomEventDispatcher<
EventMap extends Record<Keys, unknown>,
Keys extends keyof EventMap & string = keyof EventMap & string,
> {
dispatch<T extends keyof NeverNever<EventMap>>(type: T, detail: EventMap[T]): boolean
dispatch<T extends keyof PickNevers<EventMap>>(type: T): boolean
}
/**
* A strongly-typed, custom {@link EventTarget} that can dispatch and listen for events.
*
* 1. Define an event map
* ```ts
* export interface CustomEventMap {
* "my-event": { message: string }
* "simple-event": never
* }
* ```
*
* 2. Create an event emitter
* ```ts
* // By subclassing
* class MyClass extends CustomEventTarget<CustomEventMap> {
* // ...
* }
*
* // Or simply create an instance:
* const events = new CustomEventTarget<CustomEventMap>()
* ```
*
* 3. Dispatch events
* ```ts
* // Extended class
* const myClass = new MyClass()
* myClass.dispatch("my-event", { message: "Hello, world!" })
* myClass.dispatch("simple-event")
*
* // Instance
* const events = new CustomEventTarget<CustomEventMap>()
* events.dispatch("my-event", { message: "Hello, world!" })
* events.dispatch("simple-event")
* ```
*/
export class CustomEventTarget<
EventMap extends Record<Keys, unknown>,
Keys extends keyof EventMap & string = keyof EventMap & string,
> extends EventTarget {
>
extends EventTarget implements ICustomEventTarget<EventMap, Keys> {
/**
* Type-safe event dispatching.
* @see {@link EventTarget.dispatchEvent}

View File

@@ -0,0 +1,28 @@
import type { ConnectingLink } from "@/interfaces"
import type { LGraphGroup } from "@/LGraphGroup"
import type { LGraphNode } from "@/LGraphNode"
import type { CanvasPointerEvent } from "@/types/events"
export interface LGraphCanvasEventMap {
"litegraph:canvas":
| { subType: "before-change" | "after-change" }
| {
subType: "empty-release"
originalEvent?: CanvasPointerEvent
linkReleaseContext?: { links: ConnectingLink[] }
}
| {
subType: "group-double-click"
originalEvent?: CanvasPointerEvent
group: LGraphGroup
}
| {
subType: "empty-double-click"
originalEvent?: CanvasPointerEvent
}
| {
subType: "node-double-click"
originalEvent?: CanvasPointerEvent
node: LGraphNode
}
}