src/types/SETUP.md
Quick reference for the TypeScript toolchain in plotly.js.
The following dev dependencies are used for maintaining plotly.js types:
typescript — used for type-checking onlyts-node — used for running TS scripts (build helpers)@types/node, @types/d3 — provide third-party type definitionsNote: esbuild handles .ts files natively for bundling, so no extra plugins are needed for the bundling process.
tsconfig.json sets noEmit: true so that tsc never writes files. esbuild is the build system; tsc is the verifier.
Both target ES2016. strict: true is on in tsconfig.json — the type system is fully strict for the .d.ts declarations and converted TypeScript sources. The remaining JS files coexist via allowJs: true and are type-checked loosely (no strict null checks etc. on the JS side).
npm run typecheck # tsc --noEmit, errors reported, no output
npm run typecheck-watch # incremental rechecking on change
npm run schema # rebuild test/plot-schema.json + regenerate types under src/types/generated/
npm run schema-typegen-diff-check # regenerate + verify no changes to test/plot-schema.json or src/types/generated/schema.d.ts
npm run build # full production build (regenerate all files under `dist/`)
Editing during development:
# Terminal 1
npm run typecheck-watch
# Terminal 2 — bundle/dev server
npm start
Before commit:
npm run typecheck
npm run schema # if attribute files changed
CI runs both checks as separate jobs (see .github/workflows/ci.yml):
npm run typecheck # validates the type system is internally consistent
npm run schema-typegen-diff-check # verifies generated types match the schema
.tsesbuild has built-in TypeScript support — it strips types and transpiles, no extra config. The catch: when a JS file require()s a TS file with a default export, esbuild's CommonJS interop wraps it in { default: ... }. Existing project pattern is to update consumers:
// Before (JS importing JS)
var attributes = require('./attributes');
// After (JS importing TS with `export default`)
var attributes = require('./attributes').default;
This shows up when converting attributes.js → attributes.ts. See CONVERTING_ATTRIBUTES.md step 4.