Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

312
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda