Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

311
Vistas
Why does property spreading work inside Grid but not in FormControl?

Sandbox here: https://codesandbox.io/s/agitated-ardinghelli-fnoj15?file=/src/temp4.tsx:0-1206.

import { FormControl, FormControlProps, Grid, GridProps } from "@mui/material";

interface ICustomControlProps {
  gridProps?: GridProps;
  formControlProps?: FormControlProps;
}

const CustomControl = (props: ICustomControlProps) => {
  return (
    <Grid {...props.gridProps}>
      <FormControl {...props.formControlProps} />
    </Grid>
  );
};

const CustomControlVariant1 = (props: ICustomControlProps) => {
  return (
    <CustomControl
      /**
       * Below gridProps is of type GridProps.
       * It is set to object with some fixed (item, xs, sm, md) properties and spreaded props.gridProps 
       * (which is of type GridProps). 
       * But doing exactly same with formControlProps doesnt work: setting fixed component properties
       * and spreaded props.formControlProps
       */
      gridProps={{ item: true, xs: 12, sm: 12, md: 12, ...props.gridProps }}
      formControlProps={{
        component: "fieldset",  /** ERROR: Type '{ children?: React.ReactNode; classes?: Partial<FormControlClasses> & 
                                  * Partial<ClassNameMap<never>>; color?: "error" | ... 4 more ... | "warning"; ...
                                  * 264 more ...; component: string; }' is not assignable to type 'FormControlProps<"div", {}>'.
                                  * Object literal may only specify known properties, and 'component' does not exist in type 
                                  * 'FormControlProps<"div", {}>'. 
                                  * 
                                  * Object literal may only specify known properties, and 'component' 
                                  * does not exist in type 'FormControlProps<"div", {}>'.ts(2322)
                                  */
        ...props.formControlProps
      }}
    />
  );
};

Update

Note that adding another level of spreading for FormControl works:

<CustomControl
      gridProps={{ item: true, xs: 12, sm: 12, md: 12, ...props.gridProps }}

      // this works!! So, `component` is indeed on `FormControlProps`
      // which can be confirmed here: https://mui.com/api/form-control/#props
      formControlProps={{
        ...{
          component: "fieldset",
          ...props.formControlProps
        }
      }}
    />

Here is the sandbox for this code.

I find both approaches logically correct and in my opinion, both should work, but I don't understand why the first one is giving an error.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

TLDR;

In order to make TypeScript happy, you could modify ICustomControlProps as follows:

interface ICustomControlProps {
  gridProps?: GridProps;
  formControlProps?: FormControlProps & { component: React.ElementType };
}

Explanation

Let's have a look in the FormControl's declaration file:

declare const FormControl: OverridableComponent<FormControlTypeMap>;

export type FormControlProps<
  D extends React.ElementType = FormControlTypeMap['defaultComponent'],
  P = {},
> = OverrideProps<FormControlTypeMap<P, D>, D>;

Concisely, FormControlProps will gather together the props of the default component(which is a div - so, some props a specific DOM element can take in) and the props which define the FormControl component(these can be found in FormControlTypeMap, e.g. classes, fullWidth, hiddenLabel etc).

In FormControlTypeMap there surely is no component property defined and hence the error. However, OverridableComponent<FormControlTypeMap> says that receiving a component prop is accepted:

export interface OverridableComponent<M extends OverridableTypeMap> {
  <C extends React.ElementType>(
    props: {
      /**
       * The component used for the root node.
       * Either a string to use a HTML element or a component.
       */
      component: C;
    } & OverrideProps<M, C>,
  ): JSX.Element;
  (props: DefaultComponentProps<M>): JSX.Element;
}

So, you can safely use FormControl like this: <FormControl component={...} />, but wrapping it in another component, like this:

interface ICustomControlProps {
  gridProps?: GridProps;
  formControlProps?: FormControlProps;
}

const CustomControl = (props: ICustomControlProps) => {
  return (
    <Grid {...props.gridProps}>
      <FormControl {...props.formControlProps} />
    </Grid>
  );
};

will require you to specify that a component prop is also allowed on ICustomControlProps.formControlProps:

interface ICustomControlProps {
  gridProps?: GridProps;
  formControlProps?: FormControlProps & { component: React.ElementType };
}

As to why this works:

formControlProps={{
  ...{
    component: "fieldset",
    ...props.formControlProps
  }
}}

the answer seems to be found in this issue, more specifically in this comment, which says that ... creates a subtype, so it's all valid.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda