#Typesafe Object config with isolated inference within parent interface. Desperate.

17 messages · Page 1 of 1 (latest)

pine ruin
#

I am trying to create a component props interface that has several top level properties for global configuration and a configuration builder for an arbitrary number of ValueAxis configration objects.

TDateKey is used to ensure that all data series object arrays at minimum have a TDateKey ie. "time". this works great for a singular ValueAxis configuration, however each subsequent confguration added will only allow its data type to be of the type created in the first one. I think this is because the first ValueAxes object defined hijacks the TData type. is there any way to have a TData type per ValueAxes object such that each one has its own typesafety? (please see codesandbox)

export interface ChartProps<
  TDateKey extends string,
  TData extends ChartTimeSeries<TDateKey>
> {
  aggregation: string;
  dateKey: TDateKey;
  id: string;
  valueAxes: ValueAxesConfig<TDateKey, TData>;
}

export type DateKeyDatum<T extends string> = {
  [key in T]: number;
};

export type ChartTimeSeries<T extends string> = DateKeyDatum<T> &
  Record<string, number>;

export interface ValueAxesConfig<
  TDateKey extends string,
  TData extends ChartTimeSeries<TDateKey>
> {
  [key: string]: {
    data: TData[];
    defaultActiveKeys: Array<keyof Omit<TData, TDateKey>>;
    seriesConfig: {
      [key in keyof Omit<TData, TDateKey>]: SeriesConfig;
    };
  };
}

export interface SeriesConfig {
  alias?: string;
  color: string;
}
        valueAxes={{
          defaultAxis: {
            data: chartData.map((datum) => ({
              metricOne: datum.metricOne,
              time: datum.time
            })),
          },
          /** How can i fix this and still have type safetly? **/
          secondaryAxis: {
            data: chartData.map((datum) => ({
              metricTwo: datum.metricTwo,
              time: datum.time
            })),
          }
        }}
      />

https://codesandbox.io/s/exciting-pascal-2q2z45?file=/src/App.tsx

exciting-pascal-2q2z45 by binaryartifex using loader-utils, react, react-dom, react-scripts

pine ruin
#

!helper

gaunt plover
#

@pine ruin I think you’ll need to do at least two things. You’ll have to refactor ValueAxesConfig, and change ChartTimeSeries to also intersect with a type that defines the data key (ie. +1 generic there)

pine ruin
#

hmm...not entirely sure how to reflect that in a way that gets those generics passed from the parent (ChartProps) to the valueaxes.....

gaunt plover
#

Similar to how the DateKeyDatum is passed around.

#

Just refactor it to extract the value definition you’ve got there to its own interface.

#

Correction No need for unions if you just add another generic for the data key.

pine ruin
#

im sorry mate im on about 4 hours sleep the last two days and this is part of a bigger push i need to do for work. im still strugglin to piece this idea together in a code sandbox in a way that works....any chance of a code snippet or two?

#

namely the generics ultimately have to bubble back up to the parent generic and as soon as it does, the arbitrary number of 'axisconfigs' all suddenly need to adhere to whatever configuration is set int he first one

gaunt plover
#

I'm trying something...

#

Yeah you do need the union.

#

Is the DateKey always "time" btw?

#

We could simplify it just to reduce some noise...

pine ruin
#

yeah lets assume its always time for now if it makes things easier

#

honestly if its enforced i can map over the raw data and change the dateAxis key to time. simple map function

gaunt plover
#

I couldn't immediately figure out how to fix that error, maybe you could give it a go, or maybe someone else could chime in.