AG Charts leverages TypeScript Generics for chart data and context. This significantly enhances the developer experience through improved code completion and compile-time validation.
Type <TDatum> Copy Link
The TDatum (default: any) generic parameter is used to specify the interface of datums in the data.
import {
AgChartOptions,
AgCharts,
BarSeriesModule,
CategoryAxisModule,
LegendModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-community";
type MyDatumType = {
country: string;
gdp: number;
region: "AMER" | "APAC" | "EMEA";
};
function unreachable(_arg: never): never {
throw new Error();
}
ModuleRegistry.registerModules([
BarSeriesModule,
CategoryAxisModule,
LegendModule,
NumberAxisModule,
]);
const options: AgChartOptions<MyDatumType> = {
title: {
text: "Country GDP by region (in USD)",
},
data: [
{ region: "AMER", country: "Brazil", gdp: 2200 },
{ region: "AMER", country: "Canada", gdp: 2000 },
{ region: "AMER", country: "United States", gdp: 25000 },
{ region: "APAC", country: "China", gdp: 17000 },
{ region: "APAC", country: "India", gdp: 3400 },
{ region: "APAC", country: "Japan", gdp: 5000 },
{ region: "EMEA", country: "France", gdp: 3000 },
{ region: "EMEA", country: "Germany", gdp: 4000 },
{ region: "EMEA", country: "South Africa", gdp: 900 },
{ region: "EMEA", country: "United Kingdom", gdp: 3200 },
],
series: [
{
type: "bar",
yKey: "gdp",
xKey: "country",
itemStyler: (params) => {
switch (params.datum.region) {
case "AMER":
return { fill: "red" };
case "APAC":
return { fill: "blue" };
case "EMEA":
return { fill: "green" };
default:
unreachable(params.datum.region);
}
},
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
type MyDatumType = {
country: string;
gdp: number;
region: 'AMER' | 'APAC' | 'EMEA';
};
const options: AgChartOptions<MyDatumType> = {
data: [
{ region: 'AMER', country: 'Brazil', gdp: 2200 },
{ region: 'AMER', country: 'Canada', gdp: 2000 },
{ region: 'AMER', country: 'United States', gdp: 25000 },
{ region: 'APAC', country: 'China', gdp: 17000 },
{ region: 'APAC', country: 'India', gdp: 3400 },
{ region: 'APAC', country: 'Japan', gdp: 5000 },
{ region: 'EMEA', country: 'France', gdp: 3000 },
{ region: 'EMEA', country: 'Germany', gdp: 4000 },
{ region: 'EMEA', country: 'South Africa', gdp: 900 },
{ region: 'EMEA', country: 'United Kingdom', gdp: 3200 },
],
series: [
{
type: 'bar',
yKey: 'gdp',
xKey: 'country',
itemStyler: (params) => {
switch (params.datum.region) {
case 'AMER':
return { fill: 'red' };
case 'APAC':
return { fill: 'blue' };
case 'EMEA':
return { fill: 'green' };
default:
// (unreachable code)
throw new Error();
}
},
},
],
/* ... */
};In this example, specifying the TDatum = MyDatumType generic parameter does the following:
Enables compile-time checks & auto-complete for the elements of the
data[]property.Enforces type-safety for the
series[].xKeyandseries[].yKey. These properties must be keys of theMyDatumTypetype.Automatically infers the type of
params.datum.regionin theitemStylercallback.
Type <TContext> Copy Link
The TContext type (default: unknown) generic parameter is used to specify the interface of the context properties.
The Context Object is arbitrary user-defined data that will be passed to all callbacks. This is useful for attaching custom state to your chart.
import {
AgCartesianChartOptions,
AgCharts,
AnimationModule,
CandlestickSeriesModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
NumberAxisModule,
TimeAxisModule,
} from "ag-charts-enterprise";
import {
Currency,
CurrencyConverter,
makeCurrencyConverter,
} from "./currencyConverter";
import { TradeDatum, getData } from "./data";
ModuleRegistry.registerModules([
AnimationModule,
CandlestickSeriesModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
NumberAxisModule,
TimeAxisModule,
]);
const options: AgCartesianChartOptions<TradeDatum, CurrencyConverter> = {
context: makeCurrencyConverter("EUR"),
title: {
text: "Stock Prices",
},
data: getData(),
series: [
{
type: "candlestick",
xKey: "date",
openKey: "open",
highKey: "high",
lowKey: "low",
closeKey: "close",
tooltip: {
renderer: ({ datum, context }) => {
if (context == null) return {};
return {
title: datum.date.toDateString(),
data: [
{
label: "Open",
value: context.formatBothCurrencies(datum.open),
},
{
label: "High",
value: context.formatBothCurrencies(datum.high),
},
{ label: "Low", value: context.formatBothCurrencies(datum.low) },
{
label: "Close",
value: context.formatBothCurrencies(datum.close),
},
],
};
},
},
},
],
axes: {
x: {
type: "time",
},
y: {
type: "number",
label: {
formatter: ({ value, context }) => {
return context?.formatUserCurrency(value);
},
},
},
},
contextMenu: {
items: [
{
showOn: "series-node",
label: "Log as USD",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "USD")),
},
{
showOn: "series-node",
label: "Log as EUR",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "EUR")),
},
{
showOn: "series-node",
label: "Log as GBP",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "GBP")),
},
{
showOn: "series-node",
label: "Log as JPY",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "JPY")),
},
{
showOn: "series-node",
label: "Log as INR",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "INR")),
},
],
},
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
function onMySelectChange(value: Currency) {
options.context = makeCurrencyConverter(value);
chart.update(options);
}
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).onMySelectChange = onMySelectChange;
}
import { TradeDatum } from "./data";
function unreachable(_arg: never): never {
throw new Error("");
}
export type Currency = "USD" | "EUR" | "GBP" | "JPY" | "INR";
export interface CurrencyConverter {
userCurrency: Currency;
formatCurrency(stockPrice: number, currency: Currency): string;
formatStockCurrency(stockPrice: number): string;
formatUserCurrency(stockPrice: number): string;
formatBothCurrencies(stockPrice: number): string;
formatLog(datum: TradeDatum, currency: Currency): string;
}
export function makeCurrencyConverter(
userCurrency: Currency,
): CurrencyConverter {
const self: CurrencyConverter = {
userCurrency,
formatCurrency(stockPrice: number, currency: Currency): string {
const convertedPrice = Math.floor(
USD_CONVERSION_RATES[currency] * stockPrice,
);
switch (currency) {
case "USD":
return `\$${convertedPrice}`;
case "EUR":
return `€${convertedPrice}`;
case "GBP":
return `£${convertedPrice}`;
case "JPY":
return `Â¥${convertedPrice}`;
case "INR":
return `₹${convertedPrice}`;
default:
unreachable(currency);
}
},
formatStockCurrency(stockPrice: number): string {
return this.formatCurrency(stockPrice, "USD");
},
formatUserCurrency(stockPrice: number): string {
return this.formatCurrency(stockPrice, this.userCurrency);
},
formatBothCurrencies(stockPrice: number): string {
if (this.userCurrency === "USD") {
return this.formatCurrency(stockPrice, "USD");
} else {
const stockFmt = this.formatStockCurrency(stockPrice);
const userFmt = this.formatUserCurrency(stockPrice);
return `${stockFmt} (${userFmt})`;
}
},
formatLog(datum: TradeDatum, currency: Currency): string {
return [
`Pricing in ${currency}:`,
` Open : ${this.formatCurrency(datum.open, currency)}`,
` High : ${this.formatCurrency(datum.high, currency)}`,
` Low : ${this.formatCurrency(datum.low, currency)}`,
` Close : ${this.formatCurrency(datum.close, currency)}`,
].join("\n");
},
};
return self;
}
const USD_CONVERSION_RATES: { [key in Currency]: number } = {
USD: 1,
EUR: 0.87,
GBP: 0.74,
JPY: 144,
INR: 86.06,
};
export type TradeDatum = {
date: Date;
open: number;
high: number;
low: number;
close: number;
};
export function getData() {
return [
{
date: new Date(2024, 0, 1),
open: 1200,
high: 1220,
low: 1180,
close: 1210,
},
{
date: new Date(2024, 0, 2),
open: 1210,
high: 1240,
low: 1200,
close: 1220,
},
{
date: new Date(2024, 0, 3),
open: 1220,
high: 1230,
low: 1190,
close: 1200,
},
{
date: new Date(2024, 0, 4),
open: 1200,
high: 1210,
low: 1170,
close: 1180,
},
{
date: new Date(2024, 0, 5),
open: 1180,
high: 1190,
low: 1150,
close: 1170,
},
{
date: new Date(2024, 0, 6),
open: 1170,
high: 1200,
low: 1160,
close: 1190,
},
{
date: new Date(2024, 0, 7),
open: 1190,
high: 1230,
low: 1180,
close: 1220,
},
{
date: new Date(2024, 0, 8),
open: 1220,
high: 1250,
low: 1210,
close: 1240,
},
{
date: new Date(2024, 0, 9),
open: 1240,
high: 1270,
low: 1230,
close: 1260,
},
{
date: new Date(2024, 0, 10),
open: 1260,
high: 1280,
low: 1250,
close: 1270,
},
{
date: new Date(2024, 0, 11),
open: 1270,
high: 1290,
low: 1240,
close: 1250,
},
{
date: new Date(2024, 0, 12),
open: 1250,
high: 1260,
low: 1220,
close: 1230,
},
{
date: new Date(2024, 0, 13),
open: 1230,
high: 1240,
low: 1200,
close: 1220,
},
{
date: new Date(2024, 0, 14),
open: 1220,
high: 1250,
low: 1210,
close: 1240,
},
{
date: new Date(2024, 0, 15),
open: 1240,
high: 1280,
low: 1230,
close: 1270,
},
{
date: new Date(2024, 0, 16),
open: 1270,
high: 1300,
low: 1250,
close: 1260,
},
{
date: new Date(2024, 0, 17),
open: 1260,
high: 1270,
low: 1230,
close: 1240,
},
{
date: new Date(2024, 0, 18),
open: 1240,
high: 1250,
low: 1200,
close: 1210,
},
{
date: new Date(2024, 0, 19),
open: 1210,
high: 1230,
low: 1180,
close: 1190,
},
{
date: new Date(2024, 0, 20),
open: 1190,
high: 1200,
low: 1150,
close: 1160,
},
{
date: new Date(2024, 0, 21),
open: 1160,
high: 1180,
low: 1130,
close: 1140,
},
{
date: new Date(2024, 0, 22),
open: 1140,
high: 1170,
low: 1120,
close: 1160,
},
{
date: new Date(2024, 0, 23),
open: 1160,
high: 1190,
low: 1150,
close: 1180,
},
{
date: new Date(2024, 0, 24),
open: 1180,
high: 1210,
low: 1170,
close: 1200,
},
{
date: new Date(2024, 0, 25),
open: 1200,
high: 1230,
low: 1190,
close: 1210,
},
{
date: new Date(2024, 0, 26),
open: 1210,
high: 1250,
low: 1200,
close: 1240,
},
{
date: new Date(2024, 0, 27),
open: 1240,
high: 1270,
low: 1230,
close: 1260,
},
{
date: new Date(2024, 0, 28),
open: 1260,
high: 1290,
low: 1240,
close: 1250,
},
{
date: new Date(2024, 0, 29),
open: 1250,
high: 1260,
low: 1210,
close: 1230,
},
{
date: new Date(2024, 0, 30),
open: 1230,
high: 1240,
low: 1200,
close: 1220,
},
];
}
In this example the TContext generic parameter is set to a CurrencyConverter object to convert stock prices from USD to a user-defined target currency.
This is used by:
- The Y-axis Label Formatter, to convert USD values to the preferred User Currency.
- The Tooltip Renderer, to render both the stock prices in USD and the User Currency (if applicable).
- The Context Menu Actions, to log converted stock prices to the console.