Typescript: How to define a type for unknown quantity of record patterns

501 Views Asked by At

I'm trying to use Nivo charts with typescript and I'm not sure how to define the type of data Nivo expects for their Bar Chart. (https://Nivo.Rocks)

I've been trying to use

  1. Object Index Signature ... {[Key: string]: string;}
  2. Record utility type ... Record<string, string>

A snippet of example data from Nivo is as folllows:

data = [
    {
        country: 'AD',
        'hot dog': 111,
        'hot dogColor': 'hsl(168, 70%, 50%)',
        burger: 19,
        burgerColor: 'hsl(123, 70%, 50%)',
        sandwich: 161,
        sandwichColor: 'hsl(91, 70%, 50%)',
        kebab: 199,
        kebabColor: 'hsl(347, 70%, 50%)',
        fries: 153,
        friesColor: 'hsl(346, 70%, 50%)',
        donut: 41,
        donutColor: 'hsl(96, 70%, 50%)',
    }
];

I attempted things similar to this...

export type NivoBarData = {
    [Key: string]: string;
    [Key: string]: number;
    nodeKeyValue?: NivoBarNodeValue;
    nodeColor?: NivoBarNodeColor;
};

export type NivoBarTitle = Record<string, string>;
export type NivoBarNodeColor = { [Key: string]: string };
export type NivoBarNodeValue = { [Key: string]: number };
2

There are 2 best solutions below

0
mochaccino On BEST ANSWER

You could improve the type by adding in the association of keys ending with Color to strings that represent colors using an intersection and template literal types:

type NivoDatum = {
    [key: `${string}Color`]: string;
} & {
    [key: string]: string | number;
};

Then it'll correctly error on incorrect types:

const datum: NivoDatum = {
    donut: 41,          // ok since it's not a color
    donutColor: 111111, // not a string
};

Playground

Maybe I'll make a PR or open an issue about this later?

4
GatesKennedy On

So...

There is an interface definition from Nivo called BarDatum and the <ResponsiveBar/> element takes BarDatum[] for its data prop.

The interface definition is as follows:

export interface BarDatum {
    [key: string]: string | number;
}