---
title: "TypeScript Generics"
framework: react
version: "14.1.0"
---

# TypeScript Generics

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>

The `TDatum` (default: `any`) generic parameter is used to specify the interface of datums in the data.

#### TDatum Generic Parameter

```tsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgChartOptions,
  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 ChartExample = () => {
  const [options, setOptions] = useState<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);
          }
        },
      },
    ],
  });

  return <AgCharts options={options} />;
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: TDatum Generic Parameter](https://www.ag-grid.com/charts/reactFunctionalTs/ts-generics/examples/type-tdatum)

```ts
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[].xKey` and `series[].yKey`. These properties must be keys of the `MyDatumType` type.
- Automatically infers the type of `params.datum.region` in the `itemStyler` callback.

## Type <TContext>

The `TContext` type (default: `unknown`) generic parameter is used to specify the interface of the `context` properties.

The [Context Object](https://www.ag-grid.com/charts/react/context/) is arbitrary user-defined data that will be passed to all callbacks. This is useful for attaching custom state to your chart.

#### TContext Generic Parameter

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AnimationModule,
  CandlestickSeriesModule,
  ContextMenuModule,
  CrosshairModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
  TimeAxisModule,
} from "ag-charts-enterprise";
import {
  Currency,
  CurrencyConverter,
  makeCurrencyConverter,
} from "./currencyConverter";
import { TradeDatum, getData } from "./data";
import clone from "clone";

ModuleRegistry.registerModules([
  AnimationModule,
  CandlestickSeriesModule,
  ContextMenuModule,
  CrosshairModule,
  LegendModule,
  NumberAxisModule,
  TimeAxisModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<
    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")),
        },
      ],
    },
  });

  const onMySelectChange = (value: Currency) => {
    const nextOptions = clone(options);

    nextOptions.context = makeCurrencyConverter(value);

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <label htmlFor="mySelect">User Currency: </label>
          <select
            id="mySelect"
            onChange={(event) => onMySelectChange(event.target.value)}
          >
            <option value="EUR">🇪🇺 Euros (€)</option>
            <option value="USD">🇺🇸 US Dollars ($)</option>
            <option value="GBP">🇬🇧 Sterling Pound (£)</option>
            <option value="JPY">🇯🇵 Japanese Yen (¥)</option>
            <option value="INR">🇮🇳 Indian Rupee (₹)</option>
          </select>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
```

[Live example: TContext Generic Parameter](https://www.ag-grid.com/charts/reactFunctionalTs/ts-generics/examples/type-tcontext)

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](https://www.ag-grid.com/charts/react/axes-labels/#formatter), to convert USD values to the preferred User Currency.
- The [Tooltip Renderer](https://www.ag-grid.com/charts/react/tooltips/#modifying-content), to render both the stock prices in USD and the User Currency (if applicable).
- The [Context Menu Actions](https://www.ag-grid.com/charts/react/context-menu/#custom-actions), to log converted stock prices to the console.
