[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 // State
if (data.state) { if (data.state) {
const { state: { lastGroupId, lastLinkId, lastNodeId, lastRerouteId } } = data const { lastGroupId, lastLinkId, lastNodeId, lastRerouteId } = data.state
if (lastGroupId != null) this.state.lastGroupId = lastGroupId const { state } = this
if (lastLinkId != null) this.state.lastLinkId = lastLinkId if (lastGroupId != null) state.lastGroupId = lastGroupId
if (lastNodeId != null) this.state.lastNodeId = lastNodeId if (lastLinkId != null) state.lastLinkId = lastLinkId
if (lastRerouteId != null) this.state.lastRerouteId = lastRerouteId if (lastNodeId != null) state.lastNodeId = lastNodeId
if (lastRerouteId != null) state.lastRerouteId = lastRerouteId
} }
// Links // Links

View File

@@ -1,4 +1,5 @@
import type { ContextMenu } from "./ContextMenu" import type { ContextMenu } from "./ContextMenu"
import type { LGraphCanvasEventMap } from "./infrastructure/LGraphCanvasEventMap"
import type { import type {
CanvasColour, CanvasColour,
ColorOption, ColorOption,
@@ -27,7 +28,6 @@ import type {
} from "./interfaces" } from "./interfaces"
import type { LGraph } from "./LGraph" import type { LGraph } from "./LGraph"
import type { import type {
CanvasEventDetail,
CanvasMouseEvent, CanvasMouseEvent,
CanvasPointerEvent, CanvasPointerEvent,
CanvasPointerExtensions, CanvasPointerExtensions,
@@ -3151,7 +3151,7 @@ export class LGraphCanvas {
) )
} }
emitEvent(detail: CanvasEventDetail): void { emitEvent(detail: LGraphCanvasEventMap["litegraph:canvas"]): void {
this.canvas.dispatchEvent( this.canvas.dispatchEvent(
new CustomEvent("litegraph:canvas", { new CustomEvent("litegraph:canvas", {
bubbles: true, 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 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) * @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, name: string,
type: ISlotType, type: ISlotType,
extra_info?: Partial<INodeOutputSlot>, extra_info?: TProperties,
): INodeOutputSlot { ): INodeOutputSlot & TProperties {
const output = new NodeOutputSlot({ name, type, links: null }, this) const output = Object.assign(
if (extra_info) Object.assign(output, extra_info) new NodeOutputSlot({ name, type, links: null }, this),
extra_info,
)
this.outputs ||= [] this.outputs ||= []
this.outputs.push(output) 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 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) * @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 { addInput<TProperties extends Partial<INodeInputSlot>>(name: string, type: ISlotType, extra_info?: TProperties): INodeInputSlot & TProperties {
type = type || 0 type ||= 0
const input = new NodeInputSlot({ name: name, type: type, link: null }, this)
if (extra_info) Object.assign(input, extra_info) const input = Object.assign(
new NodeInputSlot({ name, type, link: null }, this),
extra_info,
)
this.inputs ||= [] this.inputs ||= []
this.inputs.push(input) this.inputs.push(input)

View File

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

View File

@@ -1,21 +1,84 @@
/** {@link Omit} all properties that evaluate to `never`. */ import type { NeverNever, PickNevers } from "@/types/utility"
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]
}
type EventListeners<T> = { type EventListeners<T> = {
readonly [K in keyof T]: ((this: EventTarget, ev: CustomEvent<T[K]>) => any) | EventListenerObject | null 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< export class CustomEventTarget<
EventMap extends Record<Keys, unknown>, EventMap extends Record<Keys, unknown>,
Keys extends keyof EventMap & string = keyof EventMap & string, Keys extends keyof EventMap & string = keyof EventMap & string,
> extends EventTarget { >
extends EventTarget implements ICustomEventTarget<EventMap, Keys> {
/** /**
* Type-safe event dispatching. * Type-safe event dispatching.
* @see {@link EventTarget.dispatchEvent} * @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 getConnectedColor(type: ISlotType): CanvasColour
getDisconnectedColor(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_color?: string
title_text_color?: string title_text_color?: string
keepAllLinksOnBypass: boolean keepAllLinksOnBypass: boolean
nodeData: any
} }
// End backwards compat // End backwards compat

View File

@@ -4,8 +4,7 @@
import type { LGraphGroup } from "../LGraphGroup" import type { LGraphGroup } from "../LGraphGroup"
import type { LGraphNode } from "../LGraphNode" import type { LGraphNode } from "../LGraphNode"
import type { ConnectingLink, LinkReleaseContextExtended } from "../litegraph" import type { LinkReleaseContextExtended } from "../litegraph"
import type { IWidget } from "./widgets"
/** For Canvas*Event - adds graph space co-ordinates (property names are shipped) */ /** For Canvas*Event - adds graph space co-ordinates (property names are shipped) */
export interface ICanvasPosition { export interface ICanvasPosition {
@@ -57,12 +56,9 @@ export interface CanvasDragEvent extends
export type CanvasEventDetail = export type CanvasEventDetail =
| GenericEventDetail | GenericEventDetail
| DragggingCanvasEventDetail
| ReadOnlyEventDetail
| GroupDoubleClickEventDetail | GroupDoubleClickEventDetail
| NodeDoubleClickEventDetail | NodeDoubleClickEventDetail
| EmptyDoubleClickEventDetail | EmptyDoubleClickEventDetail
| ConnectingWidgetLinkEventDetail
| EmptyReleaseEventDetail | EmptyReleaseEventDetail
export interface GenericEventDetail { export interface GenericEventDetail {
@@ -78,13 +74,6 @@ export interface EmptyReleaseEventDetail extends OriginalEvent {
linkReleaseContext: LinkReleaseContextExtended linkReleaseContext: LinkReleaseContextExtended
} }
export interface ConnectingWidgetLinkEventDetail {
subType: "connectingWidgetLink"
link: ConnectingLink
node: LGraphNode
widget: IWidget
}
export interface EmptyDoubleClickEventDetail extends OriginalEvent { export interface EmptyDoubleClickEventDetail extends OriginalEvent {
subType: "empty-double-click" subType: "empty-double-click"
} }
@@ -98,13 +87,3 @@ export interface NodeDoubleClickEventDetail extends OriginalEvent {
subType: "node-double-click" subType: "node-double-click"
node: LGraphNode 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. */ /** Unique graph ID. Automatically generated if not provided. */
id: UUID id: UUID
revision: number revision: number
config: LGraphConfig config?: LGraphConfig
/** Details of the appearance and location of subgraphs shown in this graph. Similar to */ /** Details of the appearance and location of subgraphs shown in this graph. Similar to */
subgraphs?: ExportedSubgraphInstance[] subgraphs?: ExportedSubgraphInstance[]
/** Definitions of re-usable objects that are referenced elsewhere in this exported graph. */ /** Definitions of re-usable objects that are referenced elsewhere in this exported graph. */
@@ -161,7 +161,7 @@ export interface ISerialisedGroup {
title: string title: string
bounding: number[] bounding: number[]
color?: string color?: string
font_size: number font_size?: number
flags?: IGraphGroupFlags 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]
}