diff --git a/src/types/ARCHITECTURE.md b/src/types/ARCHITECTURE.md index 1522d8aefb9..06d6064a0ee 100644 --- a/src/types/ARCHITECTURE.md +++ b/src/types/ARCHITECTURE.md @@ -51,7 +51,9 @@ The split: FontArray, ColorBar, HoverLabel, Domain, Pattern, TickFormatStops, LegendGroupTitle). - **Per-trace data interfaces** for all trace types (BarData, ScatterData, - IndicatorData, etc.). + IndicatorData, etc.), plus the **`Data` discriminated union** over all + of them (`Partial | Partial | …`) — narrowed via + the `type` field. - **Layout component interfaces** (LayoutAxis, Legend, Scene, Annotation, Shape, Slider, UpdateMenu, etc.) and the Layout interface itself. @@ -85,7 +87,7 @@ This split is reflected in the types: | User-facing | Internal | Where defined | |---|---|---| | `Layout` | `FullLayout` | `Layout` in `generated/schema.d.ts`; `FullLayout` in `core/layout.internal.d.ts` | -| `Data` (union over `type`) | `FullData` | `Data` in `core/data.d.ts` (union of schema `*Data` interfaces); `FullData = Data & FullDataInternals` in `core/data.internal.d.ts` | +| `Data` (union over `type`) | `FullData` | `Data` in `generated/schema.d.ts` (union of schema `*Data` interfaces); `FullData = Data & FullDataInternals` in `core/data.internal.d.ts` | | (n/a) | `GraphDiv` (the `gd` param) | `core/graph-div.internal.d.ts` — DOM element with `_fullLayout`, `_fullData`, `calcdata`, etc. | `FullData` is the discriminated union of schema trace types intersected with @@ -106,7 +108,6 @@ src/types/ ├── core/ # hand-written types for the core API │ ├── api.d.ts # public API function signatures (newPlot, etc.) │ ├── config.d.ts # Config, ToImgopts (Edits re-exported from generated) -│ ├── data.d.ts # Data union (over all schema `*Data` interfaces) │ ├── data.internal.d.ts # CalcData, FullData │ ├── events.d.ts # PlotMouseEvent, PlotlyHTMLElement, etc. │ ├── graph-div.internal.d.ts # GraphDiv, GraphContext @@ -173,6 +174,8 @@ src/types/generated/schema.d.ts │ // Trace interfaces │ export interface ScatterData { marker?: _internal.Marker; ... } │ export interface BarData { ... } + │ // Discriminated union over all traces + │ export type Data = Partial | Partial | ...; │ // Layout │ export interface LayoutAxis { autorangeoptions?: _internal.AutoRangeOptions; ... } │ export interface Layout { ... } diff --git a/src/types/GENERATOR.md b/src/types/GENERATOR.md index 018d11020b5..d5b2f188242 100644 --- a/src/types/GENERATOR.md +++ b/src/types/GENERATOR.md @@ -8,6 +8,7 @@ types into `src/types/generated/schema.d.ts`: TransitionEasing, TraceType — plus a deprecated `PlotType` alias) - Shared sub-interfaces (Font, ColorBar, HoverLabel, etc.) - Data interfaces for each trace type (BarData, ScatterData, IndicatorData, etc.) + and the `Data` discriminated union over all of them - Layout component interfaces (LayoutAxis, Legend, Scene, Annotation, etc.) and the Layout interface itself - Animation / frame / edits interfaces (AnimationOpts, Frame, Edits) @@ -90,7 +91,11 @@ so the automatic extractor skips them, but they need to be named for ### Phase 3: Trace interfaces Each trace gets an interface (`ScatterData`, `BarData`, etc.) whose -properties reference shared types where fingerprints match. +properties reference shared types where fingerprints match. After all +trace interfaces are emitted, the generator also emits the discriminated +union `Data = Partial | Partial | …` covering every +trace — narrowed via the `type` field. Adding or removing a trace in the +schema flows through automatically. ### Phase 4: Layout types @@ -191,6 +196,7 @@ src/types/generated/schema.d.ts │ AutoRangeOptions, │ Lighting, ErrorY) ├── Trace interfaces (ScatterData, BarData, ... — 49 traces) +├── Data union (`Partial<*Data>` over every trace, discriminated by `type`) ├── Layout component interfaces (LayoutAxis, Legend, Scene, Annotation, etc.) ├── Layout interface └── Animation / frames / config (AnimationOpts, Frame, Edits, ConfigBase) diff --git a/src/types/README.md b/src/types/README.md index 0c6a3293ba9..b11bd508fcb 100644 --- a/src/types/README.md +++ b/src/types/README.md @@ -48,6 +48,7 @@ The following are **auto-generated from `plot-schema.json`** by - Common enum aliases (Calendar, Dash, AxisType, PatternShape, XRef, YRef, TransitionEasing, TraceType — and a deprecated `PlotType` alias) - Data interfaces for each trace type (BarData, ScatterData, IndicatorData, etc.) + and the `Data` discriminated union over all of them - Layout component interfaces (LayoutAxis, Legend, Scene, Annotation, Shape, Slider, UpdateMenu, etc.) and the Layout interface itself - Shared sub-interfaces (Font, ColorBar, HoverLabel, LegendGroupTitle, etc.) diff --git a/src/types/core/api.d.ts b/src/types/core/api.d.ts index 32f041fe658..aa2f4bf38b0 100644 --- a/src/types/core/api.d.ts +++ b/src/types/core/api.d.ts @@ -2,9 +2,8 @@ * Public API function types for Plotly.js */ -import type { AnimationOpts, Frame, Layout } from '../generated/schema'; +import type { AnimationOpts, Data, Frame, Layout } from '../generated/schema'; import type { Config, DownloadImgopts, ToImgopts } from './config'; -import type { Data } from './data'; import type { PlotlyHTMLElement } from './events'; import type { Icon, Template } from './layout'; diff --git a/src/types/core/data.d.ts b/src/types/core/data.d.ts deleted file mode 100644 index 8d393a2e74c..00000000000 --- a/src/types/core/data.d.ts +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Data/Trace types - * - * The `Data` union covers every trace type from the schema. Use the trace's - * `type` field as the discriminator to narrow to a specific trace shape: - * - * if (trace.type === 'bar') { trace.marker?.cornerradius } - * if (trace.type === 'pie') { trace.marker?.colors } - * - * Per-trace interfaces (BarData, PieData, IndicatorData, etc.) are generated - * directly from the schema and re-exported from `generated/schema`. - */ - -import type { - BarData, - BarpolarData, - BoxData, - CandlestickData, - CarpetData, - ChoroplethData, - ChoroplethmapboxData, - ChoroplethmapData, - ConeData, - ContourcarpetData, - ContourData, - DensitymapboxData, - DensitymapData, - FunnelareaData, - FunnelData, - HeatmapData, - Histogram2dcontourData, - Histogram2dData, - HistogramData, - IcicleData, - ImageData, - IndicatorData, - IsosurfaceData, - Mesh3dData, - OhlcData, - ParcatsData, - ParcoordsData, - PieData, - PlotType, - SankeyData, - Scatter3dData, - ScattercarpetData, - ScatterData, - ScattergeoData, - ScatterglData, - ScattermapboxData, - ScattermapData, - ScatterpolarData, - ScatterpolarglData, - ScattersmithData, - ScatterternaryData, - SplomData, - StreamtubeData, - SunburstData, - SurfaceData, - TableData, - TraceType, - TreemapData, - ViolinData, - VolumeData, - WaterfallData -} from '../generated/schema'; - -export type { PlotType, TraceType }; - -/** - * Union of every trace shape. All fields are optional via `Partial<…>` — - * narrow with the `type` discriminator before accessing trace-specific - * attributes. - */ -export type Data = - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial - | Partial; diff --git a/src/types/core/events.d.ts b/src/types/core/events.d.ts index c4b14d9eebf..9355d47f2e5 100644 --- a/src/types/core/events.d.ts +++ b/src/types/core/events.d.ts @@ -8,6 +8,7 @@ import type { AnimationFrameOpts, Annotation, + Data, Frame, Layout, LayoutAxis, @@ -16,7 +17,6 @@ import type { } from '../generated/schema'; import type { Datum } from '../lib/common'; import type { Config } from './config'; -import type { Data } from './data'; // --------------------------------------------------------------------------- // Point / datum types in events diff --git a/src/types/core/graph-div.internal.d.ts b/src/types/core/graph-div.internal.d.ts index a87362a38cb..4c621c8bad7 100644 --- a/src/types/core/graph-div.internal.d.ts +++ b/src/types/core/graph-div.internal.d.ts @@ -6,9 +6,8 @@ * Commonly referred to as `gd` in the codebase. */ -import type { Layout } from '../generated/schema'; +import type { Data, Layout } from '../generated/schema'; import type { Config } from './config'; -import type { Data } from './data'; import type { CalcData, FullData } from './data.internal'; import type { FullLayout } from './layout.internal'; diff --git a/src/types/core/layout.d.ts b/src/types/core/layout.d.ts index f7f01c76096..bc25d3354ae 100644 --- a/src/types/core/layout.d.ts +++ b/src/types/core/layout.d.ts @@ -8,8 +8,7 @@ * literal utilities, and deprecated aliases. */ -import type { Layout } from '../generated/schema'; -import type { Data, TraceType } from './data'; +import type { Data, Layout, TraceType } from '../generated/schema'; import type { PlotlyHTMLElement } from './events'; // --------------------------------------------------------------------------- diff --git a/src/types/generated/schema.d.ts b/src/types/generated/schema.d.ts index f4ac6ebdae6..4e44269f5e6 100644 --- a/src/types/generated/schema.d.ts +++ b/src/types/generated/schema.d.ts @@ -12091,6 +12091,65 @@ export interface WaterfallData { zorder?: number; } +/** + * Union of every trace shape. All fields are optional via `Partial<…>` — + * narrow with the `type` discriminator before accessing trace-specific + * attributes: + * + * if (trace.type === 'bar') { trace.marker?.cornerradius } + * if (trace.type === 'pie') { trace.marker?.colors } + */ +export type Data = + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial + | Partial; + // --------------------------------------------------------------------------- // Layout component interfaces // --------------------------------------------------------------------------- diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 8233cd051b7..258c0897fa3 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -11,7 +11,6 @@ export * from './lib/common'; // Core types (public) export * from './core/api'; export * from './core/config'; -export * from './core/data'; export * from './core/events'; export * from './core/layout'; diff --git a/tasks/generate_schema_types.mjs b/tasks/generate_schema_types.mjs index 87fa258d3a2..e43a05b8e62 100644 --- a/tasks/generate_schema_types.mjs +++ b/tasks/generate_schema_types.mjs @@ -1156,6 +1156,25 @@ export function generateSchemaTypes(schema, outputPath) { chunks.push(''); } + // Discriminated union of every trace shape. All fields are optional via + // `Partial<…>` — narrow with the `type` discriminator before accessing + // trace-specific attributes. + chunks.push('/**'); + chunks.push(' * Union of every trace shape. All fields are optional via `Partial<…>` —'); + chunks.push(' * narrow with the `type` discriminator before accessing trace-specific'); + chunks.push(' * attributes:'); + chunks.push(' *'); + chunks.push(' * if (trace.type === \'bar\') { trace.marker?.cornerradius }'); + chunks.push(' * if (trace.type === \'pie\') { trace.marker?.colors }'); + chunks.push(' */'); + chunks.push('export type Data ='); + traceNames.forEach((traceName, i) => { + const interfaceName = traceNameToInterfaceName(traceName); + const sep = i === traceNames.length - 1 ? ';' : ''; + chunks.push(` | Partial<${interfaceName}>${sep}`); + }); + chunks.push(''); + // Emit layout-specific interfaces (subplots + array items) chunks.push('// ---------------------------------------------------------------------------'); chunks.push('// Layout component interfaces'); @@ -1263,6 +1282,7 @@ export function generateSchemaTypes(schema, outputPath) { if (!INTERNAL_INTERFACES.has(name)) exportedNames.add(name); } for (const traceName of traceNames) exportedNames.add(traceNameToInterfaceName(traceName)); + exportedNames.add('Data'); for (const name of subplotGroups.keys()) exportedNames.add(name); for (const name of arrayItems.keys()) exportedNames.add(name); exportedNames.add('Layout');