Search code examples
reactjstypescriptdynamiccomponents

Dynamic Typescript props on dynamic react components


The problem is, I have a set of components

const EquationOptions = (props: Equation) => { … }
const GridOptions = (props: Grid) => { … }
const OptionGroupOptions = (props: OptionGroup) => { … }
const PageOptions = (props: Page) => { … }
const SectionOptions = (props: Section) => { … }
const TableOptions = (props: Table) => { … }

const containerOptions = {
    Equation: EquationOptions,
    Grid: GridOptions,
    "Option Group": OptionGroupOptions,
    Page: PageOptions,
    Section: SectionOptions,
    Table: TableOptions,
};

And I am trying to set components dynamically as follow:

if (activeComponent) {
    const ComponentOptions = containerOptions[activeComponent?.componentType];
    options = <ComponentOptions {...activeComponent} />;
  }

Where the activeComponent variable has the type:

type ContainerModels = Equation | Grid | OptionGroup | Page | Section | Table;

The editor keeps showing an error on the ComponentOptions tag:

Type '{ variables: string[]; equation: string; componentType: "Equation" | "Grid" | "Option Group" | "Page" | "Section" | "Table"; uid: string; formComponentType: FormComponentType; identifier: string; caption: string; hint: string; } | ... 4 more ... | { ...; }' is not assignable to type 'IntrinsicAttributes & Equation & Grid & OptionGroup & Page & Section & Table'. Type '{ variables: string[]; equation: string; componentType: "Equation" | "Grid" | "Option Group" | "Page" | "Section" | "Table"; uid: string; formComponentType: FormComponentType; identifier: string; caption: string; hint: string; }' is missing the following properties from type 'Grid': templateRows, templateColumns

Though the program works because it always pass the correct type for props in the tag, I don’t know how to let typescript infer the type of the props I am passing.


Solution

  • I solved the problem just by giving a correct type to the containerOptions:

    interface ContainerOptions {
        [key: string]: Function;
    }
    
    export const containerOptions: ContainerOptions = {
        Equation: EquationOptions,
        Grid: GridOptions,
        "Option Group": OptionGroupOptions,
        Page: PageOptions,
        Section: SectionOptions,
        Table: TableOptions,
    };