3

I'm having trouble typing something like the following object.

The value for fn for both image and line are the type definition for brevity instead of including an actual function. I understand in JS these would be functions with that type.

const obj = {
  image: {
    fn: (config: ImageConfig) => ImageProps,
    Component: (props: ImageProps) => ImageElement
  },
  line: {
    fn: (config: ImageConfig) => LineProps,
    Component: (props: LineProps) => LineElement
  },

  // ...

}

How would I go about typing this in TS? I want to treat the top level keys (image and line) as arbitrary (these keys could be any value). But I want their values to always contain a key of fn and a key of Component with a relationship between the arguments and return value for fn and Component. Namely that the two compose together.

I have the following type which is easy to understand with the above:

type Element<Props, Config> = { 
  fn: (x: Config) => Props; 
  Component: (props: Props) => JSX.Element 
};

But I can't create a type that uses Element to allow for distinct generics for each entry in the object.

I can't do

type MyConfig<Props, Config> = {
  [key: string]: Element<Props, Config>
};

since I want each instance of Props and Config for each entry in the object to be different from one another. Making up my own syntax, I'd want something like:

type MyConfig = {
  [key: string]<Props, Config>: Element<Props, Config>
};

Is something like this possible to express in TS? How can I do so?

sam4444
  • 99
  • 10
  • I don't think you can make a type that expresses this exactly, but you can infer constant values with a function that enforces this. https://tsplay.dev/NVaE7w Does that meet your needs? – Alex Wayne Mar 02 '22 at 22:23
  • You might use `ObjectEntries` from https://stackoverflow.com/a/69019874/2234208 – PEZO May 28 '22 at 01:19

0 Answers0