[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

@@ -1477,11 +1477,12 @@ export class LGraph implements LinkNetwork, BaseLGraph, Serialisable<Serialisabl
// State
if (data.state) {
const { state: { lastGroupId, lastLinkId, lastNodeId, lastRerouteId } } = data
if (lastGroupId != null) this.state.lastGroupId = lastGroupId
if (lastLinkId != null) this.state.lastLinkId = lastLinkId
if (lastNodeId != null) this.state.lastNodeId = lastNodeId
if (lastRerouteId != null) this.state.lastRerouteId = lastRerouteId
const { lastGroupId, lastLinkId, lastNodeId, lastRerouteId } = data.state
const { state } = this
if (lastGroupId != null) state.lastGroupId = lastGroupId
if (lastLinkId != null) state.lastLinkId = lastLinkId
if (lastNodeId != null) state.lastNodeId = lastNodeId
if (lastRerouteId != null) state.lastRerouteId = lastRerouteId
}
// Links

View File

@@ -1,4 +1,5 @@
import type { ContextMenu } from "./ContextMenu"
import type { LGraphCanvasEventMap } from "./infrastructure/LGraphCanvasEventMap"
import type {
CanvasColour,
ColorOption,
@@ -27,7 +28,6 @@ import type {
} from "./interfaces"
import type { LGraph } from "./LGraph"
import type {
CanvasEventDetail,
CanvasMouseEvent,
CanvasPointerEvent,
CanvasPointerExtensions,
@@ -3151,7 +3151,7 @@ export class LGraphCanvas {
)
}
emitEvent(detail: CanvasEventDetail): void {
emitEvent(detail: LGraphCanvasEventMap["litegraph:canvas"]): void {
this.canvas.dispatchEvent(
new CustomEvent("litegraph:canvas", {
bubbles: true,

View File

@@ -1421,13 +1421,15 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
* @param type string defining the output type ("vec3","number",...)
* @param extra_info this can be used to have special properties of an output (label, special color, position, etc)
*/
addOutput(
addOutput<TProperties extends Partial<INodeOutputSlot>>(
name: string,
type: ISlotType,
extra_info?: Partial<INodeOutputSlot>,
): INodeOutputSlot {
const output = new NodeOutputSlot({ name, type, links: null }, this)
if (extra_info) Object.assign(output, extra_info)
extra_info?: TProperties,
): INodeOutputSlot & TProperties {
const output = Object.assign(
new NodeOutputSlot({ name, type, links: null }, this),
extra_info,
)
this.outputs ||= []
this.outputs.push(output)
@@ -1470,10 +1472,13 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
* @param type string defining the input type ("vec3","number",...), it its a generic one use 0
* @param extra_info this can be used to have special properties of an input (label, color, position, etc)
*/
addInput(name: string, type: ISlotType, extra_info?: Partial<INodeInputSlot>): INodeInputSlot {
type = type || 0
const input = new NodeInputSlot({ name: name, type: type, link: null }, this)
if (extra_info) Object.assign(input, extra_info)
addInput<TProperties extends Partial<INodeInputSlot>>(name: string, type: ISlotType, extra_info?: TProperties): INodeInputSlot & TProperties {
type ||= 0
const input = Object.assign(
new NodeInputSlot({ name, type, link: null }, this),
extra_info,
)
this.inputs ||= []
this.inputs.push(input)

View File

@@ -22,7 +22,7 @@ export type SerialisedLLinkArray = [
type: ISlotType,
]
interface ResolvedConnection {
export interface ResolvedConnection {
inputNode: LGraphNode | undefined
outputNode: LGraphNode | undefined
input: INodeInputSlot | undefined

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
}
}

View File

@@ -417,3 +417,23 @@ export interface DefaultConnectionColors {
getConnectedColor(type: ISlotType): CanvasColour
getDisconnectedColor(type: ISlotType): CanvasColour
}
/**
* Shorthand for {@link Parameters} of optional callbacks.
* @example
* ```ts
* const { onClick } = CustomClass.prototype
* CustomClass.prototype.onClick = function (...args: CallbackParams<typeof onClick>) {
* const r = onClick?.apply(this, args)
* // ...
* return r
* }
* ```
*/
export type CallbackParams<T extends ((...args: any) => any) | undefined> =
Parameters<Exclude<T, undefined>>
/**
* Shorthand for {@link ReturnType} of optional callbacks.
* @see {@link CallbackParams}
*/
export type CallbackReturn<T extends ((...args: any) => any) | undefined> = ReturnType<Exclude<T, undefined>>

View File

@@ -82,7 +82,6 @@ export interface LGraphNodeConstructor<T extends LGraphNode = LGraphNode> {
title_color?: string
title_text_color?: string
keepAllLinksOnBypass: boolean
nodeData: any
}
// End backwards compat

View File

@@ -4,8 +4,7 @@
import type { LGraphGroup } from "../LGraphGroup"
import type { LGraphNode } from "../LGraphNode"
import type { ConnectingLink, LinkReleaseContextExtended } from "../litegraph"
import type { IWidget } from "./widgets"
import type { LinkReleaseContextExtended } from "../litegraph"
/** For Canvas*Event - adds graph space co-ordinates (property names are shipped) */
export interface ICanvasPosition {
@@ -57,12 +56,9 @@ export interface CanvasDragEvent extends
export type CanvasEventDetail =
| GenericEventDetail
| DragggingCanvasEventDetail
| ReadOnlyEventDetail
| GroupDoubleClickEventDetail
| NodeDoubleClickEventDetail
| EmptyDoubleClickEventDetail
| ConnectingWidgetLinkEventDetail
| EmptyReleaseEventDetail
export interface GenericEventDetail {
@@ -78,13 +74,6 @@ export interface EmptyReleaseEventDetail extends OriginalEvent {
linkReleaseContext: LinkReleaseContextExtended
}
export interface ConnectingWidgetLinkEventDetail {
subType: "connectingWidgetLink"
link: ConnectingLink
node: LGraphNode
widget: IWidget
}
export interface EmptyDoubleClickEventDetail extends OriginalEvent {
subType: "empty-double-click"
}
@@ -98,13 +87,3 @@ export interface NodeDoubleClickEventDetail extends OriginalEvent {
subType: "node-double-click"
node: LGraphNode
}
export interface DragggingCanvasEventDetail {
subType: "dragging-canvas"
draggingCanvas: boolean
}
export interface ReadOnlyEventDetail {
subType: "read-only"
readOnly: boolean
}

View File

@@ -34,7 +34,7 @@ export interface BaseExportedGraph {
/** Unique graph ID. Automatically generated if not provided. */
id: UUID
revision: number
config: LGraphConfig
config?: LGraphConfig
/** Details of the appearance and location of subgraphs shown in this graph. Similar to */
subgraphs?: ExportedSubgraphInstance[]
/** Definitions of re-usable objects that are referenced elsewhere in this exported graph. */
@@ -161,7 +161,7 @@ export interface ISerialisedGroup {
title: string
bounding: number[]
color?: string
font_size: number
font_size?: number
flags?: IGraphGroupFlags
}

13
src/types/utility.ts Normal file
View File

@@ -0,0 +1,13 @@
/**
* General-purpose, TypeScript utility types.
*/
/** {@link Pick} only properties that evaluate to `never`. */
export type PickNevers<T> = {
[K in keyof T as T[K] extends never ? K : never]: T[K]
}
/** {@link Omit} all properties that evaluate to `never`. */
export type NeverNever<T> = {
[K in keyof T as T[K] extends never ? never : K]: T[K]
}