diff --git a/packages/g6/src/elements/combos/base-combo.ts b/packages/g6/src/elements/combos/base-combo.ts index 827337eb05a..2443d9ebe6e 100644 --- a/packages/g6/src/elements/combos/base-combo.ts +++ b/packages/g6/src/elements/combos/base-combo.ts @@ -23,14 +23,15 @@ import type { BaseNodeStyleProps } from '../nodes'; import { BaseNode } from '../nodes'; import { Icon, IconStyleProps } from '../shapes'; import { connectImage, dispatchPositionChange } from '../shapes/image'; +import { UnknownStruct } from '../../types/utility'; /** * 组合通用样式配置项 * * Common style props for combo */ -export interface BaseComboStyleProps - extends BaseNodeStyleProps, +export interface BaseComboStyleProps + extends Omit, 'childrenData'>, Prefix<'collapsed', BaseStyleProps>, Prefix<'collapsedMarker', CollapsedMarkerStyleProps> { /** @@ -60,7 +61,7 @@ export interface BaseComboStyleProps * * If the combo is collapsed, children may be empty, and the complete child element data can be obtained through childrenData */ - childrenData?: NodeLikeData[]; + childrenData?: NodeLikeData[]; /** * 组合的内边距,只在展开状态下生效 * diff --git a/packages/g6/src/elements/combos/circle.ts b/packages/g6/src/elements/combos/circle.ts index a1340cb6505..02d4f652596 100644 --- a/packages/g6/src/elements/combos/circle.ts +++ b/packages/g6/src/elements/combos/circle.ts @@ -7,29 +7,30 @@ import { subStyleProps } from '../../utils/prefix'; import { parseSize } from '../../utils/size'; import type { BaseComboStyleProps } from './base-combo'; import { BaseCombo } from './base-combo'; +import { UnknownStruct } from '../../types/utility'; /** * 圆形组合样式配置项 * * Circle combo style props */ -export interface CircleComboStyleProps extends BaseComboStyleProps {} +export interface CircleComboStyleProps extends BaseComboStyleProps {} /** * 圆形组合 * * Circle combo */ -export class CircleCombo extends BaseCombo { - constructor(options: DisplayObjectConfig) { +export class CircleCombo extends BaseCombo> { + constructor(options: DisplayObjectConfig>) { super(options); } - protected drawKeyShape(attributes: Required, container: Group): GCircle | undefined { + protected drawKeyShape(attributes: Required>, container: Group): GCircle | undefined { return this.upsert('key', GCircle, this.getKeyStyle(attributes), container); } - protected getKeyStyle(attributes: Required): GCircleStyleProps { + protected getKeyStyle(attributes: Required>): GCircleStyleProps { const { collapsed } = attributes; const keyStyle = super.getKeyStyle(attributes); @@ -41,13 +42,13 @@ export class CircleCombo extends BaseCombo { }; } - protected getCollapsedKeySize(attributes: Required): STDSize { + protected getCollapsedKeySize(attributes: Required>): STDSize { const [collapsedWidth, collapsedHeight] = parseSize(attributes.collapsedSize); const collapsedR = Math.max(collapsedWidth, collapsedHeight) / 2; return [collapsedR * 2, collapsedR * 2, 0]; } - protected getExpandedKeySize(attributes: Required): STDSize { + protected getExpandedKeySize(attributes: Required>): STDSize { const contentBBox = this.getContentBBox(attributes); const [width, height] = getBBoxSize(contentBBox); const expandedR = Math.sqrt(width ** 2 + height ** 2) / 2; diff --git a/packages/g6/src/elements/combos/rect.ts b/packages/g6/src/elements/combos/rect.ts index 9e6abc37beb..642028a4472 100644 --- a/packages/g6/src/elements/combos/rect.ts +++ b/packages/g6/src/elements/combos/rect.ts @@ -3,29 +3,30 @@ import { Rect as GRect, Group } from '@antv/g'; import { subStyleProps } from '../../utils/prefix'; import type { BaseComboStyleProps } from './base-combo'; import { BaseCombo } from './base-combo'; +import { UnknownStruct } from '../../types/utility'; /** * 矩形组合样式配置项 * * Rect combo style props */ -export interface RectComboStyleProps extends BaseComboStyleProps {} +export interface RectComboStyleProps extends BaseComboStyleProps {} /** * 矩形组合 * * Rect combo */ -export class RectCombo extends BaseCombo { - constructor(options: DisplayObjectConfig) { +export class RectCombo extends BaseCombo> { + constructor(options: DisplayObjectConfig>) { super(options); } - protected drawKeyShape(attributes: Required, container: Group): GRect | undefined { + protected drawKeyShape(attributes: Required>, container: Group): GRect | undefined { return this.upsert('key', GRect, this.getKeyStyle(attributes), container); } - protected getKeyStyle(attributes: Required): GRectStyleProps { + protected getKeyStyle(attributes: Required>): GRectStyleProps { const keyStyle = super.getKeyStyle(attributes); const [width, height] = this.getKeySize(attributes); diff --git a/packages/g6/src/elements/nodes/base-node.ts b/packages/g6/src/elements/nodes/base-node.ts index 4ffc0bc155d..6a193dc0fe6 100644 --- a/packages/g6/src/elements/nodes/base-node.ts +++ b/packages/g6/src/elements/nodes/base-node.ts @@ -29,13 +29,15 @@ import { BaseElement } from '../base-element'; import type { BadgeStyleProps, BaseShapeStyleProps, IconStyleProps, LabelStyleProps } from '../shapes'; import { Badge, Icon, Label } from '../shapes'; import { connectImage, dispatchPositionChange } from '../shapes/image'; +import { UnknownStruct } from '../../types/utility'; /** * 节点通用样式配置项 * * Base node style props */ -export interface BaseNodeStyleProps +export interface BaseNodeStyleProps< + NodeType extends UnknownStruct = UnknownStruct> extends BaseShapeStyleProps, Prefix<'label', NodeLabelStyleProps>, Prefix<'halo', BaseStyleProps>, @@ -97,7 +99,7 @@ export interface BaseNodeStyleProps * Only valid in the tree graph. If the current node is collapsed, children may be empty, and the complete child element data can be obtained through childrenData * @ignore */ - childrenData?: NodeData[]; + childrenData?: NodeData[]; /** * 是否显示节点标签 * diff --git a/packages/g6/src/runtime/data.ts b/packages/g6/src/runtime/data.ts index ffb399206a7..98abc3abe44 100644 --- a/packages/g6/src/runtime/data.ts +++ b/packages/g6/src/runtime/data.ts @@ -29,9 +29,10 @@ import { positionOf } from '../utils/position'; import { format, print } from '../utils/print'; import { dfs } from '../utils/traverse'; import { add } from '../utils/vector'; +import { InferGraphDataTypes } from '../spec/graph'; -export class DataController { - public model: GraphLib; +export class DataController { + public model: GraphLib['node'], InferGraphDataTypes['combo']>, EdgeData['edge']>>; /** * 最近一次删除的 combo 的 id @@ -132,13 +133,13 @@ export class DataController { } public getNodeData(ids?: ID[]) { - return this.model.getAllNodes().reduce((acc, node) => { - const data = toG6Data(node); + return this.model.getAllNodes().reduce['node']>[]>((acc, node) => { + const data = toG6Data(node) as NodeData['node']>; if (this.isCombo(idOf(data))) return acc; if (ids === undefined) acc.push(data); else ids.includes(idOf(data)) && acc.push(data); return acc; - }, [] as NodeData[]); + }, []); } public getEdgeDatum(id: ID) { @@ -146,23 +147,23 @@ export class DataController { } public getEdgeData(ids?: ID[]) { - return this.model.getAllEdges().reduce((acc, edge) => { + return this.model.getAllEdges().reduce['edge']>[]>((acc, edge) => { const data = toG6Data(edge); if (ids === undefined) acc.push(data); else ids.includes(idOf(data)) && acc.push(data); return acc; - }, [] as EdgeData[]); + }, []); } public getComboData(ids?: ID[]) { - return this.model.getAllNodes().reduce((acc, combo) => { + return this.model.getAllNodes().reduce['combo']>[]>((acc, combo) => { const data = toG6Data(combo); if (!this.isCombo(idOf(data))) return acc; - if (ids === undefined) acc.push(data as ComboData); - else ids.includes(idOf(data)) && acc.push(data as ComboData); + if (ids === undefined) acc.push(data); + else ids.includes(idOf(data)) && acc.push(data); return acc; - }, [] as ComboData[]); + }, []); } public getRootsData(hierarchyKey: HierarchyKey = TREE_KEY) { @@ -200,11 +201,11 @@ export class DataController { return parent ? toG6Data(parent) : undefined; } - public getChildrenData(id: ID): NodeLikeData[] { + public getChildrenData(id: ID): NodeLikeData['node'], InferGraphDataTypes['combo']>[] { const structureKey = this.getElementType(id) === 'node' ? TREE_KEY : COMBO_KEY; const { model } = this; if (!model.hasNode(id) || !model.hasTreeStructure(structureKey)) return []; - return model.getChildren(id, structureKey).map(toG6Data); + return model.getChildren(id, structureKey).map(toG6Data) as NodeLikeData['node'], InferGraphDataTypes['combo']>[]; } /** @@ -336,7 +337,7 @@ export class DataController { this.computeZIndex(data, 'add'); } - public addNodeData(nodes: NodeData[] = []) { + public addNodeData(nodes: NodeData['node']>[] = []) { if (!nodes.length) return; this.model.addNodes( nodes.map((node) => { @@ -349,7 +350,7 @@ export class DataController { this.computeZIndex({ nodes }, 'add'); } - public addEdgeData(edges: EdgeData[] = []) { + public addEdgeData(edges: EdgeData['edge']>[] = []) { if (!edges.length) return; this.model.addEdges( edges.map((edge) => { @@ -361,7 +362,7 @@ export class DataController { this.computeZIndex({ edges }, 'add'); } - public addComboData(combos: ComboData[] = []) { + public addComboData(combos: ComboData['combo']>[] = []) { if (!combos.length) return; const { model } = this; @@ -382,8 +383,8 @@ export class DataController { this.computeZIndex({ combos }, 'add'); } - public addChildrenData(parentId: ID, childrenData: NodeData[]) { - const parentData = this.getNodeLikeDatum(parentId) as NodeData; + public addChildrenData(parentId: ID, childrenData: NodeData['node']>[]) { + const parentData = this.getNodeLikeDatum(parentId) as NodeData['node']>; const childrenId = childrenData.map(idOf); this.addNodeData(childrenData); this.updateNodeData([{ id: parentId, children: [...(parentData.children || []), ...childrenId] }]); @@ -562,17 +563,17 @@ export class DataController { this.computeZIndex(data, 'update'); } - public updateNodeData(nodes: PartialNodeLikeData[] = []) { + public updateNodeData(nodes: PartialNodeLikeData['node']>>[] = []) { if (!nodes.length) return; const { model } = this; this.batch(() => { - const modifiedNodes: NodeData[] = []; + const modifiedNodes: NodeData['node']>[] = []; nodes.forEach((modifiedNode) => { const id = idOf(modifiedNode); - const originalNode = toG6Data(model.getNode(id)); + const originalNode = toG6Data(model.getNode(id)) as NodeData['node']>; if (isElementDataEqual(originalNode, modifiedNode)) return; - const value = mergeElementsData(originalNode, modifiedNode); + const value = mergeElementsData['node']>>(originalNode, modifiedNode); this.pushChange({ value, original: originalNode, type: ChangeType.NodeUpdated }); model.mergeNodeData(id, value); modifiedNodes.push(value); @@ -787,12 +788,12 @@ export class DataController { const dy = ty - comboY; const dz = tz - comboZ; - dfs( + dfs['node'], InferGraphDataTypes['combo']>>( combo, (succeed) => { const succeedId = idOf(succeed); const [x, y, z] = positionOf(succeed); - const value = mergeElementsData(succeed, { + const value = mergeElementsData['node']>>(succeed, { style: { x: x + dx, y: y + dy, z: z + dz }, }); this.pushChange({ @@ -875,7 +876,7 @@ export class DataController { const childData = toG6Data(child); const childId = idOf(childData); this.setParent(idOf(childData), grandParent, COMBO_KEY, false); - const value = mergeElementsData(childData, { + const value = mergeElementsData['node']>>(childData, { id: idOf(childData), combo: grandParent, }); diff --git a/packages/g6/src/runtime/graph.ts b/packages/g6/src/runtime/graph.ts index 83d868d741c..4d6bf29b6d4 100644 --- a/packages/g6/src/runtime/graph.ts +++ b/packages/g6/src/runtime/graph.ts @@ -62,9 +62,10 @@ import { PluginController } from './plugin'; import { TransformController } from './transform'; import { RuntimeContext } from './types'; import { ViewportController } from './viewport'; +import { InferGraphDataTypes } from '../spec/graph'; -export class Graph extends EventEmitter { - private options: GraphOptions = {}; +export class Graph extends EventEmitter { + private options: GraphOptions = {}; /** * @internal @@ -96,7 +97,7 @@ export class Graph extends EventEmitter { model: new DataController(), }; - constructor(options: GraphOptions) { + constructor(options: GraphOptions) { super(); this._setOptions(Object.assign({}, Graph.defaultOptions, options), true); this.context.graph = this; @@ -112,7 +113,7 @@ export class Graph extends EventEmitter { * @returns 配置项 | options * @apiCategory option */ - public getOptions(): GraphOptions { + public getOptions(): GraphOptions { return this.options; } @@ -127,11 +128,11 @@ export class Graph extends EventEmitter { * To update devicePixelRatio and container properties, please destroy and recreate the instance * @apiCategory option */ - public setOptions(options: GraphOptions): void { + public setOptions(options: GraphOptions): void { this._setOptions(options, false); } - private _setOptions(options: GraphOptions, isInit: boolean) { + private _setOptions(options: GraphOptions, isInit: boolean) { this.updateCanvas(options); Object.assign(this.options, inferOptions(options)); @@ -186,7 +187,7 @@ export class Graph extends EventEmitter { * @param zoomRange - 缩放区间 | zoom range * @apiCategory viewport */ - public setZoomRange(zoomRange: GraphOptions['zoomRange']): void { + public setZoomRange(zoomRange: GraphOptions['zoomRange']): void { this.options.zoomRange = zoomRange; } @@ -197,7 +198,7 @@ export class Graph extends EventEmitter { * @returns 缩放区间 | zoom range * @apiCategory viewport */ - public getZoomRange(): GraphOptions['zoomRange'] { + public getZoomRange(): GraphOptions['zoomRange'] { return this.options.zoomRange; } @@ -244,7 +245,7 @@ export class Graph extends EventEmitter { * The value of `options.combo` * @apiCategory element */ - public setCombo(combo: ComboOptions): void { + public setCombo(combo: ComboOptions['node'], InferGraphDataTypes['combo']>): void { this.options.combo = combo; this.context.model.refreshData(); } diff --git a/packages/g6/src/runtime/options.ts b/packages/g6/src/runtime/options.ts index 0f328e7952d..69c82834ccb 100644 --- a/packages/g6/src/runtime/options.ts +++ b/packages/g6/src/runtime/options.ts @@ -1,4 +1,4 @@ -import type { GraphOptions } from '../spec'; +import type { GraphData, GraphOptions } from '../spec'; /** * 基于用户传入的配置,推断出最终的配置 @@ -7,7 +7,7 @@ import type { GraphOptions } from '../spec'; * @param options - 用户传入的配置 | Configuration passed by the user * @returns 最终的配置 | Final configuration */ -export function inferOptions(options: GraphOptions): GraphOptions { +export function inferOptions(options: GraphOptions): GraphOptions { const flow = [inferLayoutOptions]; return flow.reduce((acc, infer) => infer(acc), options); } @@ -19,7 +19,7 @@ export function inferOptions(options: GraphOptions): GraphOptions { * @param options - 用户传入的配置 | Configuration passed by the user * @returns 最终的配置 | Final configuration */ -function inferLayoutOptions(options: GraphOptions): GraphOptions { +function inferLayoutOptions(options: GraphOptions): GraphOptions { if (!options.layout) return options; if (Array.isArray(options.layout)) return options; if ('preLayout' in options.layout) return options; diff --git a/packages/g6/src/spec/data.ts b/packages/g6/src/spec/data.ts index 057c69c68a4..53e2844bfc1 100644 --- a/packages/g6/src/spec/data.ts +++ b/packages/g6/src/spec/data.ts @@ -2,6 +2,8 @@ import type { ID, State } from '../types'; import type { ComboStyle } from './element/combo'; import type { EdgeStyle } from './element/edge'; import type { NodeStyle } from './element/node'; +import type { UnknownStruct } from '../types/utility'; + /** * 图数据 * @@ -26,25 +28,29 @@ import type { NodeStyle } from './element/node'; * } * ``` */ -export interface GraphData { +export interface GraphData< + N extends UnknownStruct = UnknownStruct, + E extends UnknownStruct = UnknownStruct, + C extends UnknownStruct = UnknownStruct, +> { /** * 节点数据 * * node data */ - nodes?: NodeData[]; + nodes?: NodeData[]; /** * 边数据 * * edge data */ - edges?: EdgeData[]; + edges?: EdgeData[]; /** * Combo 数据 * * combo data */ - combos?: ComboData[]; + combos?: ComboData[]; } /** @@ -52,7 +58,7 @@ export interface GraphData { * * Node data */ -export interface NodeData { +export interface NodeData { /** * 节点 ID * @@ -74,7 +80,7 @@ export interface NodeData { * * Used to store custom data of the node, which can be obtained through callback functions in the style mapping */ - data?: Record; + data?: T; /** * 节点样式 * @@ -121,7 +127,7 @@ export interface NodeData { * * Combo data */ -export interface ComboData { +export interface ComboData { /** * Combo ID * @@ -143,7 +149,7 @@ export interface ComboData { * * Used to store custom data of the Combo, which can be obtained through callback functions in the style mapping */ - data?: Record; + data?: T; /** * Combo 样式 * @@ -170,7 +176,7 @@ export interface ComboData { * * Edge data */ -export interface EdgeData { +export interface EdgeData { /** * 边 ID * @@ -204,7 +210,7 @@ export interface EdgeData { * * Used to store custom data of the edge, which can be obtained through callback functions in the style mapping */ - data?: Record; + data?: T; /** * 边样式 * diff --git a/packages/g6/src/spec/element/combo.ts b/packages/g6/src/spec/element/combo.ts index 5f9d48bc67c..3e43b5da2e4 100644 --- a/packages/g6/src/spec/element/combo.ts +++ b/packages/g6/src/spec/element/combo.ts @@ -1,59 +1,101 @@ import type { AnimationOptions } from '../../animations/types'; -import type { BaseComboStyleProps } from '../../elements/combos'; +import type { BaseComboStyleProps, CircleComboStyleProps, RectComboStyleProps } from '../../elements/combos'; import type { Graph } from '../../runtime/graph'; +import { UnknownStruct } from '../../types/utility'; import type { ComboData } from '../data'; import type { AnimationStage } from './animation'; import type { PaletteOptions } from './palette'; +type ComboDataFn = (this: Graph, datum: ComboData) => R; + +type StyleFieldComboDataFn = { + [K in keyof S]?: S[K] | ComboDataFn; +}; + +type ComboOptionsBuilder< + NodeType extends UnknownStruct = UnknownStruct, + ComboType extends UnknownStruct = UnknownStruct, + Type extends string = string, + Style extends Partial> = Partial> +> = { + /** + * 组合类型 + * + * Combo type + */ + type?: Type | ComboDataFn; + /** + * 组合样式 + * + * Combo style + */ + style?: + | Style + | ComboDataFn + | StyleFieldComboDataFn; + /** + * 组合状态样式 + * + * Combo state style + */ + state?: Record< + string, + | Style + | ComboDataFn + | StyleFieldComboDataFn + >; + /** + * 组合动画 + * + * Combo animation + */ + animation?: false | Record; + /** + * 色板 + * + * Palette + */ + palette?: PaletteOptions; +} + +export interface ComboStyle extends Partial> { + [key: string]: unknown; +} + +type CircleComboOptions = ComboOptionsBuilder< + NodeType, + ComboType, + 'circle', + CircleComboStyleProps +>; + +type RectComboOptions = ComboOptionsBuilder< + NodeType, + ComboType, + 'rect', + RectComboStyleProps +>; + +type CustomComboOptions = ComboOptionsBuilder< + NodeType, + ComboType, + string, + ComboStyle +>; + + /** * Combo 配置项 * * Combo spec */ -export interface ComboOptions { - /** - * 组合类型 - * - * Combo type - */ - type?: string | ((this: Graph, datum: ComboData) => string); - /** - * 组合样式 - * - * Combo style - */ - style?: - | ComboStyle - | ((this: Graph, data: ComboData) => ComboStyle) - | { - [K in keyof ComboStyle]: ComboStyle[K] | ((this: Graph, data: ComboData) => ComboStyle[K]); - }; - /** - * 组合状态样式 - * - * Combo state style - */ - state?: Record< - string, - | ComboStyle - | ((this: Graph, data: ComboData) => ComboStyle) - | { - [K in keyof ComboStyle]: ComboStyle[K] | ((this: Graph, data: ComboData) => ComboStyle[K]); - } - >; - /** - * 组合动画 - * - * Combo animation - */ - animation?: false | Record; - /** - * 色板 - * - * Palette - */ - palette?: PaletteOptions; -} +export type ComboOptions< + NodeType extends UnknownStruct = UnknownStruct, + ComboType extends UnknownStruct = UnknownStruct, +> = + | CircleComboOptions + | RectComboOptions + | CustomComboOptions; export interface StaticComboOptions { style?: ComboStyle; @@ -61,7 +103,3 @@ export interface StaticComboOptions { animation?: false | Record; palette?: PaletteOptions; } - -export interface ComboStyle extends Partial { - [key: string]: any; -} diff --git a/packages/g6/src/spec/element/state.ts b/packages/g6/src/spec/element/state.ts new file mode 100644 index 00000000000..dfae1157fd8 --- /dev/null +++ b/packages/g6/src/spec/element/state.ts @@ -0,0 +1,7 @@ +/** + * 内置状态 + * + * Built-in states + * @see https://g6.antv.antgroup.com/en/manual/element/state + */ +export type BuiltInState = 'selected' | 'active' | 'highlight' | 'inactive' | 'disable'; diff --git a/packages/g6/src/spec/graph.ts b/packages/g6/src/spec/graph.ts index b4b60544b82..34c3812ef40 100644 --- a/packages/g6/src/spec/graph.ts +++ b/packages/g6/src/spec/graph.ts @@ -1,7 +1,7 @@ import type { AnimationEffectTiming } from '../animations/types'; import type { BehaviorOptions } from './behavior'; import type { CanvasOptions } from './canvas'; -import type { GraphData } from './data'; +import type { ComboData, EdgeData, GraphData, NodeData } from './data'; import type { ComboOptions } from './element/combo'; import type { EdgeOptions } from './element/edge'; import type { NodeOptions } from './element/node'; @@ -11,6 +11,12 @@ import type { ThemeOptions } from './theme'; import type { TransformOptions } from './transform'; import type { ViewportOptions } from './viewport'; +export type InferGraphDataTypes = { + node: D['nodes'] extends NodeData[] ? N : never; + edge: D['edges'] extends EdgeData[] ? E : never; + combo: D['combos'] extends ComboData[] ? C : never; +}; + /** * Graph 配置项 * @@ -25,7 +31,7 @@ import type { ViewportOptions } from './viewport'; * ``` */ -export interface GraphOptions extends CanvasOptions, ViewportOptions { +export interface GraphOptions extends CanvasOptions, ViewportOptions { /** * 启用或关闭全局动画 * @@ -45,7 +51,7 @@ export interface GraphOptions extends CanvasOptions, ViewportOptions { * * See [Data](/en/api/data/graph-data) */ - data?: GraphData; + data?: D; /** * 布局配置项 * @@ -85,7 +91,7 @@ export interface GraphOptions extends CanvasOptions, ViewportOptions { * * See [Combo](/en/api/elements/combos/base-combo) */ - combo?: ComboOptions; + combo?: ComboOptions['node'], InferGraphDataTypes['combo']>; /** * 主题 * diff --git a/packages/g6/src/types/data.ts b/packages/g6/src/types/data.ts index 2133c62c9b3..cec29fbf4f1 100644 --- a/packages/g6/src/types/data.ts +++ b/packages/g6/src/types/data.ts @@ -1,5 +1,6 @@ import type { ComboData, EdgeData, NodeData } from '../spec/data'; import type { ID } from '../types'; +import { UnknownStruct } from './utility'; export type DataID = { nodes?: ID[]; @@ -7,7 +8,7 @@ export type DataID = { combos?: ID[]; }; -export type NodeLikeData = NodeData | ComboData; +export type NodeLikeData = NodeData | ComboData; export type ElementDatum = NodeData | EdgeData | ComboData; @@ -46,10 +47,14 @@ export type PartialEdgeData = * * G6 data update optional data */ -export type PartialGraphData = { - nodes?: PartialNodeLikeData[]; - edges?: PartialEdgeData[]; - combos?: PartialNodeLikeData[]; +export type PartialGraphData< + N extends UnknownStruct = UnknownStruct, + E extends UnknownStruct = UnknownStruct, + C extends UnknownStruct = UnknownStruct, +> = { + nodes?: PartialNodeLikeData>[]; + edges?: PartialEdgeData>[]; + combos?: PartialNodeLikeData>[]; }; /** diff --git a/packages/g6/src/utils/graphlib.ts b/packages/g6/src/utils/graphlib.ts index 8d5033f6cd6..b1cce0f4ff3 100644 --- a/packages/g6/src/utils/graphlib.ts +++ b/packages/g6/src/utils/graphlib.ts @@ -1,12 +1,13 @@ import type { Edge, Graph as Graphlib, Node } from '@antv/graphlib'; import { TREE_KEY } from '../constants'; -import type { ComboData, EdgeData, NodeData } from '../spec'; +import type { ComboData, EdgeData, GraphData, NodeData } from '../spec'; import { NodeLikeData } from '../types/data'; import { idOf } from './id'; import { isEdgeData } from './is'; +import { InferGraphDataTypes } from '../spec/graph'; -export function toGraphlibData(datums: EdgeData): Edge; -export function toGraphlibData(datums: NodeLikeData): Node; +export function toGraphlibData(datums: EdgeData['edge']>): Edge['edge']>>; +export function toGraphlibData(datums: NodeLikeData['node'], InferGraphDataTypes['combo']>): Node['node'], InferGraphDataTypes['combo']>>; /** * 将 NodeData、EdgeData、ComboData 转换为 graphlib 的数据结构 * @@ -14,12 +15,12 @@ export function toGraphlibData(datums: NodeLikeData): Node; * @param data - 节点、边、combo 数据 | node, combo data * @returns graphlib 数据 | graphlib data */ -export function toGraphlibData(data: NodeData | EdgeData | ComboData): Node | Edge { +export function toGraphlibData(data: NodeData['node']> | EdgeData['edge']> | ComboData['combo']>): Node['node'], InferGraphDataTypes['combo']>> | Edge['edge']>> { const { id = idOf(data), style, data: customData, ...rest } = data; const _data = { ...data, style: { ...style }, data: { ...customData } }; - if (isEdgeData(data)) return { id, data: _data, ...rest } as Edge; - return { id, data: _data } as Node; + if (isEdgeData(data)) return { id, data: _data, ...rest } as Edge['edge']>>; + return { id, data: _data } as Node['node'], InferGraphDataTypes['combo']>>; } export function toG6Data(data: Edge): T;