Search code examples
typescripttypescript-genericsreact-typescript

How do dynamically access a type via function parameter


I have something like the following:

const activeFormDesign = {
    fields: {
    },
    elements: {
    },
    groups: {
    },
    layouts: {
        section: SectionLayout,
        header: Header,
        title: Title,
        description: Description,
        goal: Goal,
    },
};

Each property of layouts refers to a functional component with distinct props. My goal is that someone can access the FC of a given layout by providing the key, and the returned FC will know what props its supposed to have.

I thought I could do something like this:

export function getLayoutTemplate(type: keyof typeof activeFormDesignTemplate['layouts']): FC<typeof activeFormDesignTemplate['layouts'][type] {
    return activeFormDesignTemplate.layouts[type];

}

const Goal = getLayoutTemplate('goal');

<Goal />

The parameter type works great. But the return type throws an error that "type cannot be used as an index type". I mean... it kind of makes sense. I understand that a truly dynamic type couldn't be inferred. But if I'm statically typing it out, as in getLayoutTemplate('goal') I would think that it could.

I feel like there's a way to do this, but I've not quite figured it out and would appreciate any help!


Solution

  • Assuming that SectionLayout, Header, etc. are already of type React.FC, you only need to make the function generic over K and remove the React.FC around the return type.

    export function getLayoutTemplate<
      K extends keyof typeof activeFormDesign["layouts"]
    >(type: K): typeof activeFormDesign['layouts'][K] {
        return activeFormDesign.layouts[type];
    }
    

    The parameter type is now of type K and you can use K to index typeof activeFormDesign['layouts'] for the return type.

    But you are gonna need to find a way at runtime to convert whatever SectionLayout, Header, etc. are into a React.FC if they are not already of type React.FC


    Playground