Using Plotly.js with TypeScript in JavaScript
How to use Plotly.js with TypeScript, including the types it ships and how to type figures, layouts, configs, and events.
Plotly Studio: Transform any dataset into an interactive data application in minutes with AI. Try Plotly Studio now.
Using Plotly.js with TypeScript
Since v4, Plotly.js ships its own TypeScript type definitions. package.json points
"types" at lib/index.d.ts, so they are picked up automatically.
Most of the types are generated from the plot schema and that information is included
in the type definitions
Importing
The package provides a default namespace, named exports, and a global Plotly
namespace, so all of these work:
import Plotly from 'plotly.js';
// or
import * as Plotly from 'plotly.js';
// or
import { newPlot } from 'plotly.js';
import type { Layout, Data, TraceType } from 'plotly.js';
A minimal typed figure:
import { newPlot } from 'plotly.js';
import type { Data, Layout } from 'plotly.js';
const data: Data[] = [{ type: 'scatter', x: [1, 2, 3], y: [4, 5, 6] }];
const layout: Partial<Layout> = { title: { text: 'Demo' } };
await newPlot(div, data, layout);
Typing trace data
Data is the union of every trace's data object, and it discriminates on type.
Annotating a figure as Data[] therefore gets each entry checked against the right
trace shape:
const data: Data[] = [
{ type: 'bar', x: ['a', 'b'], y: [1, 2] }, // checked as BarData
{ type: 'scatter', x: [1, 2], mode: 'lines' }, // checked as ScatterData
];
Per-trace interfaces (ScatterData, BarData, HeatmapData, ChoroplethData, …)
are exported too. Reach for them when a value is guaranteed to be one trace type —
for example a helper that builds a BarData to push into a Data[] — and prefer the
Data union everywhere else.
Typing layout and config
Layout describes the layout object you pass in, so use Partial<Layout>: nearly
every field is optional, and the full interface would require all of them.
Config types the config argument.
import type { Config, Layout } from 'plotly.js';
const layout: Partial<Layout> = {
title: { text: 'Quarterly revenue' },
yaxis: { tickformat: '$,.0f' },
};
const config: Partial<Config> = { responsive: true, showSendToCloud: false };
Note that Layout and Data are input shapes. The post-coerce internal shapes
that Plotly computes from them (often called "FullLayout" and "FullData") are
deliberately not exported.
Typing events
Event payloads have their own interfaces, and PlotlyHTMLElement types the graph
div that newPlot resolves to:
import { newPlot } from 'plotly.js';
import type { PlotMouseEvent, PlotRelayoutEvent } from 'plotly.js';
const gd = await newPlot(div, data, layout);
gd.on('plotly_click', (event: PlotMouseEvent) => {
console.log(event.points[0].x, event.points[0].y);
});
gd.on('plotly_relayout', (event: PlotRelayoutEvent) => {
console.log(event['xaxis.range[0]']);
});
PlotlyEventName is the union of names accepted by on(), once(), and
removeListener().
What else is exported
| Category | Exports |
|---|---|
| Layout components | LayoutAxis, Legend, Annotation, Shape, Slider, UpdateMenu, Scene, and the other component interfaces |
| Config and image export | Config, ToImgopts, DownloadImgopts, ToImageButtonOptions, ModeBarDefaultButtons, ModeBarButton, Icon |
| Enums | String-literal unions such as TraceType, AxisType, Calendar, Dash, PatternShape, XRef, YRef, MarkerSymbol, HoverInfo — use these instead of string to get narrowing on attribute values |
| Shared sub-interfaces | Font, ColorBar, HoverLabel, Pattern, Domain, LegendGroupTitle, TickFormatStops |
| Events | PlotMouseEvent, PlotHoverEvent, PlotSelectionEvent, PlotRelayoutEvent, PlotRestyleEvent, LegendClickEvent, SliderChangeEvent, PlotlyEventName |
| Animation and frames | AnimationOpts, Frame, Transition, TransitionEasing |
| Templates | Template, TemplateFigure, ValidateTemplateResult |
| DOM and values | PlotlyHTMLElement, Datum, TypedArray, Color, ColorScale |
PlotType is an alias for TraceType, so existing imports keep compiling. New code
should prefer TraceType.