Sammy
Sammy

Reputation: 3697

Spreading Extended Type Props into Typescript Interface

I have the following interfaces:

interface ButtonProps {
  name: string;
}

interface IconButtonProps {
  name: string;
  icon: string;
}

I'm trying to create the type for the following component:

<MyGenericComponent component={button} name="button">...
<MyGenericComponent component={iconButton} name="icon-button" icon="icon">...

The idea is that I'm unable to type the interface that would represent MyGenericComponentProps so that it can accept a react component in the component prop as long as all other props given to it are those that the given component would accept!

Something like this:

interface MyGenericComponentProps<T> extends T {
  component: React.FC<T>;
}

...where T above can be ButtonProps or IconButtonProps. I know I cannot extend T because it's unknown statically, but then how do I ensure that the rest of the props given are those of either ButtonProps or IconButtonProps?

UPDATE: here's the component definition after answer:

import React from 'react';
import { ButtonProps, IconButtonProps } from '@material-ui/core';

type MyGenericComponentProps<T> = {
    component: React.FC<T>;
} & {
    [key in keyof T]: T[key];
};

const MyGenericComponent = <T extends object>({ component, ...props }: MyGenericComponentProps<T>) => {
    // ... more code here
    const Component = component;
    return <Component {...props} />;
};

export default MyGenericComponent;

Upvotes: 2

Views: 1484

Answers (2)

If it doesn't make sense what kind of TS entity will be used (type or interface) then you can type it as a type instead of an interface:

type MyGenericComponentProps<T> = {
  component: React.FC<T>;
} & {
  [key in keyof T]: T[key];
}

[UPDATE]:

You need to modify and even simplify some fragments:

type MyGenericComponentProps<T> = {
  component: React.FC<T>;
  props: T; 
}

const MyGenericComponent = <T extends object>({component: Component, props}: MyGenericComponentProps<T>) => {
  // ... more code here
  return <Component {...props}/>;
};

Upvotes: 2

Shashan Sooriyahetti
Shashan Sooriyahetti

Reputation: 878

interface ButtonProps {
  name: string;
}

interface IconButtonProps extends ButtonProps{
  icon?: string;
}

and

interface MyGenericComponentProps<IconButtonProps>{
  component: React.FC<IconButtonProps>;
}

do not know about react, but with typescript you can do extend interfaces and declare optional properties. Then this would accept ButtonProps and IconButtonProps

Upvotes: 1

Related Questions