mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 06:19:58 +00:00
## Summary
- Replace `any` types with proper TypeScript types in core type
definitions
- Add generics to `SettingParams`, `setting.get<T>()`, and
`setting.set<T>()` for type-safe setting access
- Add `NodeExecutionOutput` interface for `onExecuted` callback
- Change function parameters from `any` to `unknown` where appropriate
## Type Research
Performed GitHub code search across custom node repositories to
understand actual usage patterns:
**`onExecuted` output properties** (used in rgthree-comfy,
ComfyUI-KJNodes, ComfyUI-ExLlama-Nodes, comfy_mtb, etc.):
- `output.text` - string or string array for text display nodes
- `output.images`, `output.audio`, `output.video` - media outputs
- `output.ui.items` - complex debug/preview data with `input`, `text`,
`b64_images`
**`extensionManager.setting.get/set`** (used in ComfyUI-Crystools,
ComfyUI-Copilot, etc.):
- Returns various types (boolean, number, string, objects)
- Now uses generics: `setting.get<boolean>('MyExt.Setting')`
**`ComfyExtension` custom properties** (used in rgthree-comfy,
ComfyUI-Manager):
- `aboutPageBadges`, `commands`, custom methods
- Kept as `any` index signature since extensions add arbitrary
properties
## Changes
| File | Change |
|------|--------|
| `extensionTypes.ts` | Generic `setting.get<T>()` and
`setting.set<T>()`, typed Toast options |
| `litegraph-augmentation.d.ts` | `onExecuted(output:
NodeExecutionOutput)` |
| `metadataTypes.ts` | GLTF index signatures `any` → `unknown` |
| `apiSchema.ts` | New `NodeExecutionOutput` interface |
| `settings/types.ts` | `SettingOnChange<T>`, `SettingMigration<T>`,
`SettingParams<TValue>` |
| `nodeDefSchema.ts` | `validateComfyNodeDef(data: unknown)` |
| `workflowSchema.ts` | `isSubgraphDefinition(obj: unknown)` |
| `telemetry/types.ts` | `checkForCompletedTopup(events: AuditLog[])` |
## Test plan
- [x] `pnpm typecheck` passes
- [x] `pnpm test:unit` passes (3732 tests)
- [x] `pnpm lint` passes
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7337-fix-improve-type-safety-in-type-definitions-2c66d73d365081bdbc30e916cac607d6)
by [Unito](https://www.unito.io)
84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
/*
|
|
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 { app } from '@/scripts/app'
|
|
import { type DOMWidget } from '@/scripts/domWidget'
|
|
import { ComfyWidgets } from '@/scripts/widgets'
|
|
import { useExtensionService } from '@/services/extensionService'
|
|
|
|
useExtensionService().registerExtension({
|
|
name: 'Comfy.PreviewAny',
|
|
async beforeRegisterNodeDef(nodeType, nodeData) {
|
|
if (nodeData.name === 'PreviewAny') {
|
|
const onNodeCreated = nodeType.prototype.onNodeCreated
|
|
|
|
nodeType.prototype.onNodeCreated = function () {
|
|
onNodeCreated ? onNodeCreated.apply(this, []) : undefined
|
|
|
|
const showValueWidget = ComfyWidgets['MARKDOWN'](
|
|
this,
|
|
'preview',
|
|
['MARKDOWN', {}],
|
|
app
|
|
).widget as DOMWidget<HTMLTextAreaElement, string>
|
|
|
|
const showValueWidgetPlain = ComfyWidgets['STRING'](
|
|
this,
|
|
'preview',
|
|
['STRING', { multiline: true }],
|
|
app
|
|
).widget as DOMWidget<HTMLTextAreaElement, string>
|
|
|
|
const showAsPlaintextWidget = ComfyWidgets['BOOLEAN'](
|
|
this,
|
|
'previewMode',
|
|
[
|
|
'BOOLEAN',
|
|
{ label_on: 'Markdown', label_off: 'Plaintext', default: false }
|
|
],
|
|
app
|
|
)
|
|
|
|
showAsPlaintextWidget.widget.callback = (value) => {
|
|
showValueWidget.hidden = !value
|
|
showValueWidget.options.hidden = !value
|
|
showValueWidgetPlain.hidden = value
|
|
showValueWidgetPlain.options.hidden = value
|
|
}
|
|
|
|
showValueWidget.hidden = true
|
|
showValueWidget.options.hidden = true
|
|
showValueWidget.options.read_only = true
|
|
showValueWidget.element.readOnly = true
|
|
showValueWidget.element.disabled = true
|
|
showValueWidget.serialize = false
|
|
|
|
showValueWidgetPlain.hidden = false
|
|
showValueWidgetPlain.options.hidden = false
|
|
showValueWidgetPlain.options.read_only = true
|
|
showValueWidgetPlain.element.readOnly = true
|
|
showValueWidgetPlain.element.disabled = true
|
|
showValueWidgetPlain.serialize = false
|
|
}
|
|
|
|
const onExecuted = nodeType.prototype.onExecuted
|
|
|
|
nodeType.prototype.onExecuted = function (message) {
|
|
onExecuted === null || onExecuted === void 0
|
|
? void 0
|
|
: onExecuted.apply(this, [message])
|
|
|
|
const previewWidgets =
|
|
this.widgets?.filter((w) => w.name === 'preview') ?? []
|
|
|
|
for (const previewWidget of previewWidgets) {
|
|
const text = message.text ?? ''
|
|
previewWidget.value = Array.isArray(text) ? (text[0] ?? '') : text
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|