fix: add explicit type annotations to extension callback parameters (#8966)

Fixes #8882

Adds explicit type annotations to all extension callback parameters
(`nodeCreated`, `beforeRegisterNodeDef`, `addCustomNodeDefs`) across 14
core extension files. While the types were already inferred from the
`ComfyExtension` interface, explicit annotations improve readability and
make the code self-documenting.

## Changes

- Annotate `node` parameter as `LGraphNode` in all `nodeCreated`
callbacks
- Annotate `nodeType` as `typeof LGraphNode` and `nodeData` as
`ComfyNodeDef` in all `beforeRegisterNodeDef` callbacks
- Annotate `defs` as `Record<string, ComfyNodeDef>` in
`addCustomNodeDefs`
- Add necessary type imports where missing

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8966-fix-add-explicit-type-annotations-to-extension-callback-parameters-30b6d73d36508125b074f509aa38145f)
by [Unito](https://www.unito.io)
This commit is contained in:
Christian Byrne
2026-02-20 01:26:11 -08:00
committed by GitHub
parent 6902e38e6a
commit a1c54ad7aa
14 changed files with 60 additions and 22 deletions

View File

@@ -4,6 +4,7 @@ import { useChainCallback } from '@/composables/functional/useChainCallback'
import type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'
import { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { LLink } from '@/lib/litegraph/src/litegraph'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import { app } from '@/scripts/app'
function applyToGraph(this: LGraphNode, extraLinks: LLink[] = []) {
@@ -190,7 +191,7 @@ function onCustomFloatCreated(this: LGraphNode) {
app.registerExtension({
name: 'Comfy.CustomWidgets',
beforeRegisterNodeDef(nodeType, nodeData) {
beforeRegisterNodeDef(nodeType: typeof LGraphNode, nodeData: ComfyNodeDef) {
if (nodeData?.name === 'CustomCombo')
nodeType.prototype.onNodeCreated = useChainCallback(
nodeType.prototype.onNodeCreated,

View File

@@ -1,3 +1,4 @@
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useExtensionService } from '@/services/extensionService'
import { processDynamicPrompt } from '@/utils/formatUtil'
@@ -6,7 +7,7 @@ import { processDynamicPrompt } from '@/utils/formatUtil'
useExtensionService().registerExtension({
name: 'Comfy.DynamicPrompts',
nodeCreated(node) {
nodeCreated(node: LGraphNode) {
if (node.widgets) {
// Locate dynamic prompt text widgets
// Include any widgets with dynamicPrompts set to true, and customtext

View File

@@ -1993,11 +1993,11 @@ const ext: ComfyExtension = {
await GroupNodeConfig.registerFromWorkflow(nodes, missingNodeTypes)
}
},
addCustomNodeDefs(defs) {
addCustomNodeDefs(defs: Record<string, ComfyNodeDef>) {
// Store this so we can mutate it later with group nodes
globalDefs = defs
},
nodeCreated(node) {
nodeCreated(node: LGraphNode) {
if (GroupNodeHandler.isGroupNode(node)) {
;(node as LGraphNode & { [GROUP]: GroupNodeHandler })[GROUP] =
new GroupNodeHandler(node)

View File

@@ -1,3 +1,4 @@
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import type { NodeOutputWith } from '@/schemas/apiSchema'
import { api } from '@/scripts/api'
import { app } from '@/scripts/app'
@@ -11,7 +12,7 @@ type ImageCompareOutput = NodeOutputWith<{
useExtensionService().registerExtension({
name: 'Comfy.ImageCompare',
async nodeCreated(node) {
async nodeCreated(node: LGraphNode) {
if (node.constructor.comfyClass !== 'ImageCompare') return
const [oldWidth, oldHeight] = node.size

View File

@@ -1,9 +1,10 @@
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useExtensionService } from '@/services/extensionService'
useExtensionService().registerExtension({
name: 'Comfy.ImageCrop',
async nodeCreated(node) {
async nodeCreated(node: LGraphNode) {
if (node.constructor.comfyClass !== 'ImageCropV2') return
node.hideOutputImages = true

View File

@@ -17,6 +17,7 @@ import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'
import type { IStringWidget } from '@/lib/litegraph/src/types/widgets'
import { useToastStore } from '@/platform/updates/common/toastStore'
import type { NodeOutputWith } from '@/schemas/apiSchema'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
type Load3dPreviewOutput = NodeOutputWith<{
result?: [string?, CameraState?, string?]
@@ -327,7 +328,7 @@ useExtensionService().registerExtension({
return createExportMenuItems(load3d)
},
async nodeCreated(node) {
async nodeCreated(node: LGraphNode) {
if (node.constructor.comfyClass !== 'Load3D') return
const [oldWidth, oldHeight] = node.size
@@ -423,7 +424,10 @@ useExtensionService().registerExtension({
useExtensionService().registerExtension({
name: 'Comfy.Preview3D',
async beforeRegisterNodeDef(_nodeType, nodeData) {
async beforeRegisterNodeDef(
_nodeType: typeof LGraphNode,
nodeData: ComfyNodeDef
) {
if ('Preview3D' === nodeData.name) {
// @ts-expect-error InputSpec is not typed correctly
nodeData.input.required.image = ['PREVIEW_3D']
@@ -462,7 +466,7 @@ useExtensionService().registerExtension({
}
},
async nodeCreated(node) {
async nodeCreated(node: LGraphNode) {
if (node.constructor.comfyClass !== 'Preview3D') return
const [oldWidth, oldHeight] = node.size

View File

@@ -7,8 +7,10 @@
* - A user adds a 3D node from the node menu
*/
import { useExtensionService } from '@/services/extensionService'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import { app } from '@/scripts/app'
import { useExtensionService } from '@/services/extensionService'
import { useExtensionStore } from '@/stores/extensionStore'
import type { ComfyExtension } from '@/types/comfy'
@@ -54,7 +56,10 @@ function isLoad3dNodeType(nodeTypeName: string): boolean {
useExtensionService().registerExtension({
name: 'Comfy.Load3DLazy',
async beforeRegisterNodeDef(nodeType, nodeData) {
async beforeRegisterNodeDef(
nodeType: typeof LGraphNode,
nodeData: ComfyNodeDef
) {
if (isLoad3dNodeType(nodeData.name)) {
// Inject mesh_upload spec flags so WidgetSelect.vue can detect
// Load3D's model_file as a mesh upload widget without hardcoding.

View File

@@ -3,6 +3,8 @@ Preview Any - original implement from
https://github.com/rgthree/rgthree-comfy/blob/main/py/display_any.py
upstream requested in https://github.com/Kosinkadink/rfcs/blob/main/rfcs/0000-corenodes.md#preview-nodes
*/
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import { app } from '@/scripts/app'
import { type DOMWidget } from '@/scripts/domWidget'
import { ComfyWidgets } from '@/scripts/widgets'
@@ -10,7 +12,10 @@ import { useExtensionService } from '@/services/extensionService'
useExtensionService().registerExtension({
name: 'Comfy.PreviewAny',
async beforeRegisterNodeDef(nodeType, nodeData) {
async beforeRegisterNodeDef(
nodeType: typeof LGraphNode,
nodeData: ComfyNodeDef
) {
if (nodeData.name === 'PreviewAny') {
const onNodeCreated = nodeType.prototype.onNodeCreated

View File

@@ -1,3 +1,5 @@
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import { applyTextReplacements } from '@/utils/searchAndReplace'
import { app } from '../../scripts/app'
@@ -21,7 +23,10 @@ const saveNodeTypes = new Set([
app.registerExtension({
name: 'Comfy.SaveImageExtraOutput',
async beforeRegisterNodeDef(nodeType, nodeData) {
async beforeRegisterNodeDef(
nodeType: typeof LGraphNode,
nodeData: ComfyNodeDef
) {
if (saveNodeTypes.has(nodeData.name)) {
const onNodeCreated = nodeType.prototype.onNodeCreated
// When the SaveImage node is created we want to override the serialization of the output name widget to run our S&R

View File

@@ -8,6 +8,7 @@ import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'
import type { NodeOutputWith, ResultItem } from '@/schemas/apiSchema'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
type SaveMeshOutput = NodeOutputWith<{
'3d'?: ResultItem[]
@@ -26,7 +27,10 @@ const inputSpec: CustomInputSpec = {
useExtensionService().registerExtension({
name: 'Comfy.SaveGLB',
async beforeRegisterNodeDef(_nodeType, nodeData) {
async beforeRegisterNodeDef(
_nodeType: typeof LGraphNode,
nodeData: ComfyNodeDef
) {
if ('SaveGLB' === nodeData.name) {
// @ts-expect-error InputSpec is not typed correctly
nodeData.input.required.image = ['PREVIEW_3D']
@@ -65,7 +69,7 @@ useExtensionService().registerExtension({
return createExportMenuItems(load3d)
},
async nodeCreated(node) {
async nodeCreated(node: LGraphNode) {
if (node.constructor.comfyClass !== 'SaveGLB') return
const [oldWidth, oldHeight] = node.size

View File

@@ -88,7 +88,10 @@ async function uploadFile(
// present.
app.registerExtension({
name: 'Comfy.AudioWidget',
async beforeRegisterNodeDef(nodeType, nodeData) {
async beforeRegisterNodeDef(
nodeType: typeof LGraphNode,
nodeData: ComfyNodeDef
) {
if (
[
'LoadAudio',
@@ -179,7 +182,10 @@ app.registerExtension({
app.registerExtension({
name: 'Comfy.UploadAudio',
async beforeRegisterNodeDef(_nodeType, nodeData: ComfyNodeDef) {
async beforeRegisterNodeDef(
_nodeType: typeof LGraphNode,
nodeData: ComfyNodeDef
) {
if (nodeData?.input?.required?.audio?.[1]?.audio_upload === true) {
nodeData.input.required.upload = ['AUDIOUPLOAD', {}]
}
@@ -419,7 +425,7 @@ app.registerExtension({
}
},
async nodeCreated(node) {
async nodeCreated(node: LGraphNode) {
if (node.constructor.comfyClass !== 'RecordAudio') return
await useAudioService().registerWavEncoder()

View File

@@ -1,3 +1,4 @@
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import {
type ComfyNodeDef,
type InputSpec,
@@ -35,7 +36,7 @@ const createUploadInput = (
app.registerExtension({
name: 'Comfy.UploadImage',
beforeRegisterNodeDef(_nodeType, nodeData: ComfyNodeDef) {
beforeRegisterNodeDef(_nodeType: typeof LGraphNode, nodeData: ComfyNodeDef) {
const { input } = nodeData ?? {}
const { required } = input ?? {}
if (!required) return

View File

@@ -1,4 +1,5 @@
import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useToastStore } from '@/platform/updates/common/toastStore'
import { api } from '../../scripts/api'
@@ -66,7 +67,7 @@ app.registerExtension({
}
}
},
nodeCreated(node) {
nodeCreated(node: LGraphNode) {
if ((node.type, node.constructor.comfyClass !== 'WebcamCapture')) return
// @ts-expect-error fixme ts strict error

View File

@@ -16,7 +16,7 @@ import { assetService } from '@/platform/assets/services/assetService'
import { createAssetWidget } from '@/platform/assets/utils/createAssetWidget'
import { isCloud } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import type { InputSpec } from '@/schemas/nodeDefSchema'
import type { ComfyNodeDef, InputSpec } from '@/schemas/nodeDefSchema'
import { app } from '@/scripts/app'
import {
ComfyWidgets,
@@ -563,7 +563,10 @@ export function mergeIfValid(
app.registerExtension({
name: 'Comfy.WidgetInputs',
async beforeRegisterNodeDef(nodeType, _nodeData) {
async beforeRegisterNodeDef(
nodeType: typeof LGraphNode,
_nodeData: ComfyNodeDef
) {
// @ts-expect-error adding extra property
nodeType.prototype.convertWidgetToInput = function (this: LGraphNode) {
console.warn(