Material-ui: Erro de tipo de escrita no componente retornado por withStyles ()

Criado em 28 set. 2017  ·  55Comentários  ·  Fonte: mui-org/material-ui

Ao usar withStyles() hoc no texto digitado, estou recebendo o seguinte erro ao tentar usar o componente retornado:

Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<App> & Readonly<{ children?: ReactNode; }> & Reado...'.
  Type '{}' is not assignable to type 'Readonly<WithStyles<"main">>'.
    Property 'classes' is missing in type '{}'.
  • [x] Pesquisei os problemas deste repositório e acredito que não seja uma duplicata.

Parece que essa alteração na definição do tipo pode estar relacionada a esse problema.

Comportamento esperado

Dado o código do componente App abaixo, devo ser capaz de usar o componente <App /> sem o erro de tipo como fiz em 1.0.0-beta.10.

Comportamento Atual

Dado o código do componente App abaixo, tentar usar <App /> resulta no erro mencionado.

O código

import * as React from 'react';
import { withStyles } from 'material-ui/styles';

const styles = {
    main: {
        marginTop: 48,
        padding: 10,
    },
    foo: {
        margin: 0,
    },
};

interface Props {
    message: string;
};

type ClassNames = { classes: { [className in keyof typeof styles]: string } };

class App extends React.Component<Props & ClassNames> {
    render() {
        const { classes, message } = this.props;
        return (
            <div className={classes.main}>
                <div className={classes.foo} >
                    Hello World! {message}
                </div>
            </div>
        );
    }
}

export default withStyles(styles)(App);

Contexto

O código funcionou bem em 1.0.0-beta.10, quando atualizei para 1.0.0-beta.12, recebi o erro de tipo.

No trecho de código fornecido, usei o truque keyof typeof styles para não precisar definir uma lista de nomes de classes duas vezes (não gosto da repetitividade). Também tentei outras variações:

type ClassNames = WithStyles<keyof typeof styles>;

e fazendo isso da maneira mais comum (como visto em styles.spec.tsx ):

type ComponentClassNames = 'main' | 'foo';
type ClassNames = WithStyles<ComponentClassNames>;

Ainda obtenho o mesmo erro.

Parece que a definição de tipo anterior retornaria um componente cujo tipo de props seria StyledComponentProps que tem uma propriedade opcional classes . A nova definição ...

<P, C extends React.ComponentClass<P & StyledComponentProps<Names>>>(
    component: C
  ): C;

... retorna o mesmo tipo C do componente, isso significa que passar ClassNames que não está marcado como opcional se propaga para o componente retornado. Vejo aqui mencionado o uso de Partial<> que considero um hack feio.

Seu Ambiente

| Tech | Versão |
| -------------- | --------- |
| Material-UI | 1.0.0-beta.12 |
| React | 15.6.1 |
| navegador | Chrome 61.0.3163.100 |

discussion typescript

Comentários muito úteis

Resolvi usando recompor

exemplo

import { StyleRules, Theme, withStyles } from "material-ui/styles";
import * as React from "react";
import { compose } from "recompose";

interface IProps {
    classes?: any; // <-- add question mark
    text: string;
}

const styles = (theme: Theme): StyleRules => ({
    root: {

    },
});

@compose(
    withStyles(styles),
)
export class MyComponent extends React.Component<IProps> {
    render() {
        const { classes, text } = this.props;
        return (
            <div className={classes.root}>
                {text}
            </div>
        );
    }
}

Todos 55 comentários

@cfilipov ao decorar uma classe de componente, você deve usar StyledComponentProps vez de WithStyles , e se estiver no modo de verificação de tipo estrito, você precisará usar o operador de asserção não nulo ! para extrair os campos de classes . Este é um meio-termo para permitir o uso de withStyles como decorador de classe. Os decoradores de classe no TypeScript sofrem com a limitação de que seu tipo de retorno deve corresponder ao tipo de argumento. Apenas uma opção devido a essas limitações é possível:

  1. não suporta o uso de withStyles como decorador de classe
  2. exigem que você passe um classes prop fictício ao construir um elemento do tipo de componente decorado (o compromisso anterior, que era indiscutivelmente mais irritante )
  3. requer que classes seja considerado anulável dentro do componente, forçando você a usar o operador ! ao acessar seus campos ( o compromisso atual )

Eu recomendo fortemente que, se o seu componente não tiver estado, você use um componente funcional sem estado, que exigirá menos anotações de tipo e será mais seguro para o tipo:

export default withStyles(styles)<Props>(({ classes, message }) => (
  <div className={classes.main}>
    <div className={classes.foo}>
      Hello World! {message}
    </div>
  </div>
));

Vejo mencionado aqui o uso de Partial <>, o que considero um hack feio.

Se você ler meu seguimento a esse comentário, verá que Partial<> não é necessário.

Se você ler meu seguimento a esse comentário, verá que Partial <> não é obrigatório.

Eu vi seu comentário sobre Partial<> . Usar StyledComponentProps essencialmente equivale à mesma coisa (é usar Partial<> nessa definição). Minha reclamação agora é que os nomes das classes devem ser acessados ​​com ! (como você mencionou). Acho que passar por um classes prop fictício ou exigir o uso de ! são ambos compromissos ruins.

Para esclarecer, acho que o problema raiz que estou tendo aqui é a escolha de introduzir uma regressão ao hoc em um esforço para contornar uma limitação de um recurso experimental do texto datilografado. Admito alguns preconceitos, já que não ligo para decoradores, enquanto outros claramente se importam, mas a compensação aqui não faz sentido para mim.

@cfilipov minha primeira refatoração das tipificações withStyles foi escolher a opção (1), isto é, tornar as tipificações completamente corretas para os componentes de classe e função, às custas de usar withStyles como decorador de classe . Então, recebi um feedback de que usar a sintaxe do decorador era uma solicitação comum, então mudei para a opção (3). Estou feliz em rever essa decisão; Eu também preferiria a segurança de tipos a apoiar os decoradores em seu estado semifuncional atual.

Sim, entendo o desejo de apoiar um pedido popular como este. Também quero usar decoradores, mas sempre encontro muitos problemas com eles (fora do mui), então, pessoalmente, decidi não usá-los até que estejam prontos.

Parece que você compartilha minha preocupação e não tenho muito mais a acrescentar, então espero que outras pessoas possam fornecer feedback nesse sentido para ajudar a influenciá-lo.

Mudei para beta.13 de beta.10 para ver se algo mudou e sim, este é um problema real. Para jogar meus 2 centavos aqui, para mim, decoradores são experimentais. Eles obviamente poderiam ser alterados no futuro. E até então eu apoiaria totalmente a maneira 100% precisa. Eu preferiria ter uma segurança de tipos coerente para hackear meus tipos para fazer as coisas funcionarem.

8550 parece mais uma evidência de que as pessoas estão confusas com isso, e devemos considerar não oferecer suporte a @withStyles() como decorador (em TypeScript).

Isso é o que pareceria "decorar" uma classe se tornássemos as digitações corretas:

type NonStyleProps = {
  text: string
};

const styles = {
  root: {
    backgroundColor: 'red'
  }
};

const DecoratedComponent = withStyles(styles)(
  class extends React.Component<NonStyleProps & WithStyles<'root'>> {
    render() {
      return (
        <div className={this.props.classes.root}>
          {this.props.text}
        </div>
      );
    }
  }
);

@pelotom Ainda estou para avançar do beta.10 por causa desse problema. Eu já fiz comentários sobre o estilo de uma classe com o método de conexão do Redux. Acho que é relativamente fácil e robusto. em # 8059, o terceiro comentário sou eu mesmo com os tipos.

@pelotom Muito obrigado por nos educar sobre este assunto. Sou um grande usuário de decoradores de TS, mas, nesse caso, ficaria feliz se withStyles deixasse de usar seu suporte de decoração para ter uma melhor segurança de digitação.

devemos considerar não oferecer suporte a @withStyles () como decorador (no TypeScript).

@pelotom Pessoalmente , sou a favor dessa mudança. @sebald O que você deseja fazer aqui?

É uma mudança simples; Eu fui em frente e abri um PR, caso você queira ir com ele 🙂

@pelotom as

interface IStyles {
    // styles interface
}
interface IHeaderInfoStyles {
    classes: any;
}
interface IHeaderInfoProps {
    // properties resulting from dispatches
}
interface IHeaderInfoInjectedProps {
   // props injected from parent if any
}
interface IHeaderInfoDispatchProps {
    // dispatches
}
interface IHeaderInfoState {
    // your state for the class
}

type HeaderInfoProps = IHeaderInfoProps & IHeaderInfoInjectedProps & IHeaderInfoDispatchProps & IHeaderInfoStyles;

class HeaderInfo extends Component<HeaderInfoProps, IHeaderInfoState> {

export const HeaderInfo_container = withStyles<IHeaderInfoInjectedProps, IStyles>(styles)(
    connect<IHeaderInfoProps, IHeaderInfoDispatchProps, (IHeaderInfoInjectedProps & IHeaderInfoStyles)>(mapStateToProps, mapDispatchToProps)(HeaderInfo),
);

@marcusjpressedan withStyles não usa mais 2 parâmetros de tipo, e você não deveria ter que fornecer um parâmetro de tipo para estilos (pode ser inferido de styles ). Você deveria ser capaz de escrever

withStyles(styles)<NonStyleProps>(...);

Se você fornecer os tipos para mapStateToProps e mapDispatchToProps posso mostrar como seria o seu exemplo.

tl; dr; Vamos fazer as mudanças e ver qual é a reação, eu acho 👷🏻


@oliviertassinari @pelotom ¯_ (ツ) _ / ¯ Eu não uso decoradores, então pessoalmente, eu realmente não me importo com essa mudança, porque eu não fui afetado. Mas parece que muitas pessoas se importam com esse "recurso". É por isso que o adicionamos em primeiro lugar. Isso é IMHO o que tem prioridade aqui.

Estou muito feliz com as mudanças de withStyles , mas quando você dá uma olhada em outras bibliotecas mais funcionais, como ramda ou recompose , as digitações não são tão rígidas, também não são superprotegidos. Freqüentemente, você precisa passar um genérico, que representa o valor de retorno de uma função. Não é bonito, mas funcionará para 99,9% dos usuários.

Por que não podemos trazer de volta as velhas tipificações que funcionavam para as pessoas que usavam decoradores? Como ele tinha dois genéricos, podemos ter as duas tipificações lado a lado.

Além disso, estou um pouco confuso quais são os problemas das pessoas com decoradores (em relação a "não funcionar"). Afinal, bibliotecas como Angular e https://nestjs.com/ fazem uso pesado deles. Em nosso caso, as pessoas poderiam apenas adicionar WithStyles aos adereços e tudo bem.

@sebald

Por que não podemos trazer de volta as velhas tipificações que funcionavam para as pessoas que usavam decoradores? Como ele tinha dois genéricos, podemos ter as duas tipificações lado a lado.

Não tenho certeza do que você quer dizer. Nunca houve qualquer digitação que permitisse às pessoas usar decoradores sem dor. A primeira implementação sofria de # 8267, que era que você não podia construir um elemento de um componente decorado sem passar um falso classes prop, por exemplo, <StyledComp classes={{} as any} /> . A segunda implementação (atual) sofre do problema inverso, que classes é visto como potencialmente undefined dentro da classe de componente. Se você deseja usar decoradores TypeScript em sua forma atual, essas são suas apenas 2 opções; escolha o seu veneno.

A terceira maneira é usar o tipo correto, de forma que classes seja definido dentro da classe, mas não precise ser passado como um prop. Para ter essas duas condições, você precisa desistir dos decoradores.

@pelotom Sim, desculpe. Você tem razão. Realmente não é o meu dia ... 🤐 Então vamos nos fundir!

@sebald

Além disso, estou um pouco confuso quais são os problemas das pessoas com decoradores (em relação a "não funcionar"). Afinal, bibliotecas como Angular e https://nestjs.com/ fazem uso pesado deles.

Não tenho certeza de como eles são usados ​​no Angular, mas certamente há casos de uso em que decoradores podem ser usados ​​sem dor; basicamente, se o decorador não precisar alterar o tipo de classe que está decorando, eles funcionam bem. Essa não é a situação que temos aqui; withStyles precisa mudar o tipo do componente que decora.

@pelotom Sim, exatamente. É apenas a mutação que é ruim. Na verdade, a forma como o TS atualmente implementa decoradores pode até ser boa para os usuários Angular, já que os decoradores AFAIK firmam contratos com o framework, como "registrar essa classe como um componente" ou "adicionar metadados para que eu possa usar isso no DI "... Deus, mesmo escrever sobre isso me faz sentir 🤢

@pelotom o motivo pelo qual tenho os tipos da mesma forma que faço é que ele forneceu Segurança de tipo para meus componentes. Atualmente os tipos não têm segurança de tipo quando se trata de componentes. Os injectedProps no meu exemplo são os tipos exigidos pelo componente para funcionar. Os tipos de conexão de react-redux precisam ser Props que vêm de mapStateToProps e DispatchProps que vêm de mapDispatchToProps .

No final, deve haver injetedProps para que meu componente pai saiba que preciso injetá-los ou meu projeto não será compilado. (é isso que eu quero). Essa mudança vai migrar de volta para esse tipo de segurança?

@marcusjpressedan novamente, se você puder fornecer um exemplo completo (mas mínimo) que estava compilando no beta 10, posso mostrar como migrar. AFAIK, a nova versão deve ser tão expressiva e mais segura de digitar do que antes.

@pelotom Pergunta boba, há uma maneira de ser notificado quando um novo lançamento for concluído?

@wcandillon Siga-nos no Twitter.

@pelotom Eu

Editar

Eu descobri.

Estou entrando nesta discussão um pouco tarde, mas tenho visto um erro semelhante ao mencionado aqui, e ainda estou para determinar como posso corrigi-lo. Estou usando [email protected] e [email protected] .

const LoginForm = withStyles(styles)(
    class extends React.Component<WithStyles<'root' | 'button'>, ILoginFormState> {
    // ...
    }
);

render(
  <MuiThemeProvider theme={theme}>
    <LoginForm />
  </MuiThemeProvider>,
  document.getElementById('login-form')
);

A mensagem de erro que estou recebendo neste caso específico é:

Type '{}' is not assignable to type 'IntrinsicAttributes & WithStyles<"root" | "button"> & StyledComponentP...'.
  Type '{}' is not assignable to type 'WithStyles<"root" | "button" | "progress" | "textField">'.
    Property 'classes' is missing in type '{}'.
 not assignable to type 'WithStyles<"root" | "button" | "progress" | "textField">'.
    Property 'classes' is missing in type '{}'.

ao decorar uma classe de componente, você deve usar StyledComponentProps em vez de WithStyles

@pelotom - existe um exemplo disso em algum lugar? Estou tendo muitos problemas para determinar como definir o estilo de uma classe de componente com estado no TypeScript.

@iamjem , é um pouco difícil dizer, já que você não forneceu styles , mas parece que o primeiro problema é que você tem mais chaves de classe mencionadas em styles do que está mencionando em WithStyles<...> . Eu acho que se você mudar para

const LoginForm = withStyles(styles)(
    class extends React.Component<WithStyles<keyof typeof styles>, ILoginFormState> {
    // ...
    }
);

deve cuidar da primeira questão. Então parece que há um segundo problema, que o tipo resultante de LoginForm é

React.ComponentType<WithStyles<"root" | "button"> & StyledComponentProps<"root" | "button">>

o que obviamente não é correto; parece que a ausência de adereços sem estilo está confundindo o sistema de tipos. Você pode ajudar sendo explícito sobre o que são os adereços sem estilo, passando {} como um argumento de tipo:

const LoginForm = withStyles(styles)<{}>( // <-- note the type argument
    class extends React.Component<WithStyles<keyof typeof styles>, ILoginFormState> {
    // ...
    }
);

Desculpe, é tão complicado, gostaria de saber uma maneira mais fácil de fazer essas coisas funcionarem!

Isso funcionou! Obrigado pela ajuda rápida @pelotom. Eu uso o React há muito tempo, mas recentemente comecei a usar o Material-ui e pensei em experimentar o Typescript enquanto estou nisso. Desnecessário dizer que estou descobrindo que há alguns casos extremos em que é difícil dizer como tornar o Typcript feliz.

Resolvi usando recompor

exemplo

import { StyleRules, Theme, withStyles } from "material-ui/styles";
import * as React from "react";
import { compose } from "recompose";

interface IProps {
    classes?: any; // <-- add question mark
    text: string;
}

const styles = (theme: Theme): StyleRules => ({
    root: {

    },
});

@compose(
    withStyles(styles),
)
export class MyComponent extends React.Component<IProps> {
    render() {
        const { classes, text } = this.props;
        return (
            <div className={classes.root}>
                {text}
            </div>
        );
    }
}

Eu estava lutando contra esse problema (e # 8704), sem nenhum resultado claro nos últimos dias. Então, aceitei o conselho de

você deve usar StyledComponentProps vez de WithStyles

e pesquisou no GitHub por maneiras semelhantes de resolver isso. E eu encontrei UM exemplo de trabalho 😂. É um bom, porém, e resolveu meu problema - contêiner separado e componente com TypeScript sendo um cookie feliz: exemplo mencionado aqui ( Observação: no meu caso, o mapeamento de componente está em um arquivo de contêiner separado, mas a ideia é o mesmo.).

Se alguém achar que esta é uma solução ruim , estou aberto a quaisquer mudanças e ideias. Agora, estou feliz que meu código parou de reclamar.

type Styles = 'foo';
const styles: StyleRulesCallback<Styles> = (theme: Theme) => ({
    foo: {
        position: 'relative',
    }
});

interface Props {
  something: string;
}

class Sidebar extends React.Component<Props & WithStyles<Styles>> {
    render() {
        const { classes, something } = this.props;

        return (
                    <div className={classes.foo}>{something}</div>
        );
    }
}

export default withStyles(styles)<Props>(Sidebar);

Não quero criar um novo problema, mas tentei tudo o que vi na documentação, exemplo, e passei nos problemas, mesmo com o recompose, mas não consigo fazer meu componente funcionar quando adiciono algumas propriedades a ele.
E os recursos que encontrei são principalmente com versões mais antigas do TS, MUI ou mesmo React.

Este é meu componente:

import React from 'react';
import AppBar from 'material-ui/AppBar';
import { withStyles, WithStyles, StyleRulesCallback } from 'material-ui/styles';

const styles: StyleRulesCallback<'positionFixed'> = () => ({
  positionFixed: {
    top: 'auto',
    bottom: 0,
  },
});

const decorate = withStyles(styles);

interface Props {
   someProp: string;
};

export const BottomNav = decorate<Props>(
  class extends React.Component<Props & WithStyles<'positionFixed'>, {}> {
    render() {
      return (
        <AppBar />
      );
    }
  }
);

export default BottomNav;

E o erro é:

TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & Props & StyledComponentProps<"positionFixed"> & { children?: ReactNode; }'.
  Type '{}' is not assignable to type 'Props'.
    Property 'someProp' is missing in type '{}'.

Sou bastante iniciante em TS, mas acho a página de documentação e o exemplo um tanto confusos e / ou incompletos.

Se vocês têm alguma ideia, obrigado ;-)

@otroboe você está

<BottomNav />

Nesse caso, o problema é que você precisa fornecer o someProp prop (que é exigido de acordo com sua definição de Props ):

<BottomNav someProp="foo" />

Que vergonha de mim ... Oh, que vergonha de mim.
Eu estava tão focado na integração do TS que esqueci de olhar em volta e dar alguns passos para trás.

Muito obrigado @pelotom : smile:

@otroboe Remova também a duplicação de strings ...

type Styles = 'positionFixed';

Gostaria que aquele fosse mais fácil ...

Sim, eu também fiz isso, obrigado: +1:

Acabei de enfrentar o mesmo problema, mas acontece que ele ocorre apenas se eu tiver inicializado o objeto styles no mesmo arquivo que minha classe ou função. Como alternativa, se estou importando os estilos de outro arquivo, não recebo este erro.

Alguma pista de por que isso acontece?

@ nishmeht7 você pode postar um snippet independente?

@pelotom Acabei de fazer um e funciona bem no meu ambiente de sandbox. No momento, estou trabalhando em um aplicativo grande e ainda estou no mui versão 1.2.2, enquanto minha versão do env do sandbox é a mais recente. Portanto, suponho que, depois de atualizar as versões, não serei capaz de reproduzir meu erro.

Segui o exemplo de um formulário básico de https://material-ui.com/demos/selects/, mas recebi reclamações de que theme não tem root (usando o último texto datilografado e material- ui), e nenhuma classe estava sendo aplicada ao elemento form . Tentei acompanhar a discussão acima, mas parece inconclusiva. E, de fato, faltava na lista de classes herdadas o nome da classe gerada para form . Se eu adicionasse o nome de classe gerado manualmente (encontrado em withStyles com console.log(theme) nas ferramentas de desenvolvimento de elementos de inspeção, tudo bem, então, aparentemente, a classe estava sendo gerada corretamente. Não estava sendo passado por withStyles para o form entanto, o elemento

Portanto, voltei aos estilos por enquanto, até que isso seja resolvido:

<form style = {{display:'flex',flexWrap:'wrap'}} autoComplete="off">

@HenrikBechmann Você tentou seguir a documentação de estilos para o https://material-ui.com/guides/typescript/

Obrigado @lookfirst! Eu olhei (embora não primeiro :-)) naquele documento e usei

export default withStyles({
  root: {
    display: 'flex',
    flexWrap: 'wrap',
  },
})(BaseForm)

(passando o objeto em vez da função)

... que evitou os erros de digitação e permitiu a injeção da classe gerada.

Esperançosamente, as outras dicas ajudarão com construções mais complexas.

Também confirmei que a estrutura mais complexa para a função styles funciona (injeta um className gerado em form ):

import React from 'react'

import { withStyles, createStyles, Theme } from '@material-ui/core/styles'

/*
    patterned after first demo https://material-ui.com/demos/selects/ for 3.03
    use Typsecript fixes from here: https://material-ui.com/guides/typescript/
*/

const styles = (theme:Theme) => createStyles({
  root: {
    display: 'flex',
    flexWrap: 'wrap',
  },
})

class BaseForm extends React.Component<any,any> {

    render() {
        const { classes } = this.props

        return (
            <form className = {classes.root} autoComplete="off">
                {this.props.children}
            </form>
        )
    }
}

export default withStyles(styles)(BaseForm)

Edit: @ eps1lon apontou que isso é desnecessário com o uso de WithStyles !

Tive algum sucesso usando ReturnType<T> para gerar ClassKey para mim:

import * as React from 'react';

import withStyles, {
  StyledComponentProps, 
  StyleRulesCallback,
} from '@material-ui/core/styles/withStyles';

import { Theme } from '@material-ui/core/styles/createMuiTheme';

const overrideStyles = (theme: Theme) => ({
  root: {
    display: 'flex',
    flexDirection: 'column',
  },
});

type Props = StyledComponentProps<keyof ReturnType<typeof overrideStyles>>;

class MyComponent extends React.PureComponent<Props> {
  render() {
    return <div className={this.props.classes.root}></div>;
  }
}

export default withStyles(overrideStyles as StyleRulesCallback, {withTheme: true})(MyComponent);

Usar keyof ReturnType<typeof styleOverrides> como StyledComponentProps ClassKey obterá as chaves do objeto retornado por overrideStyles e evitará que você tenha que manter uma lista dessas chaves manualmente . A única falha que notei é um erro de tipo se eu não lançar overrideStyles as StyleRulesCallback na chamada withStyles . Não estou 100% certo do porquê. Acho que withStyles não está entendendo o que overrideStyles é por algum motivo.

Para esclarecer esse tipo bastante elaborado, typeof styleOverrides resolve a função que retorna o objeto de estilo. ReturnType<T> obterá o próprio objeto de estilo. keyof obterá as chaves do objeto de estilo.

@chrislambe Você deve verificar o guia de texto datilografado . Você não deve precisar usar ReturnType etc. createStyles e WithStyles devem ser suficientes como ajudantes.

@ eps1lon Oh ei, muito legal! Obrigado!

fwiw Estou gostando do par createStyles / withStyles cada vez mais à medida que os uso. Promove código organizado, lida com todos os meus problemas de estilo / texto datilografado e, se eu quiser css condicional local, apenas crio atributos de estilo local, que obviamente têm precedência sobre as classes.

Agradável!!

Seguindo o guia de datilografia com @ material-ui / [email protected] , recebo Test does not have required attribute classes em:

import React from 'react'
import { Theme, WithStyles, withStyles, createStyles } from '@material-ui/core/styles'

const styles = (theme: Theme) => createStyles({
  root: {
    color: theme.palette.action.active
  },
})

interface Props extends WithStyles<typeof styles> {
  asd: boolean
}

class TestComponent extends React.Component<Props> {

  render() {
    const { classes } = this.props

    return (
      <div className={classes.root}>
      </div>
    )
  }
}

const Test = withStyles(styles)(TestComponent)

const a = () => <Test asd={true}/>

@valoricDe Você resolveu seu problema?

@TrejGun Acabei de verificar. Com um componente funcional e @ material-ui / [email protected] eu não tenho esse problema

Eu realmente não entendo.
Seguindo a documentação aqui: https://material-ui.com/guides/typescript/#augmenting -your-props-using-withstyles
parece apenas resultar no problema deste problema original. Quando você usa o componente em algum lugar, o texto digitado exige que você _passar_ a propriedade classes como um suporte em vez de perceber que será _injetado_ por withStyles.

Estou lendo essas edições há algumas horas e não estou entendendo direito. Qualquer ajuda seria tão boa neste ponto.

Em relação a esta sugestão acima

@cfilipov ao decorar uma classe de componente, você deve usar StyledComponentProps vez de WithStyles , e se estiver no modo de verificação de tipo estrito, você precisará usar o operador de asserção não nulo ! para extrair os campos de classes . Este é um meio-termo para permitir o uso de withStyles como decorador de classe. Os decoradores de classe no TypeScript sofrem com a limitação de que seu tipo de retorno deve corresponder ao tipo de argumento. Apenas uma opção devido a essas limitações é possível:

  1. não suporta o uso de withStyles como decorador de classe
  2. exigem que você passe um classes prop fictício ao construir um elemento do tipo de componente decorado (o compromisso anterior, que era indiscutivelmente mais irritante )
  3. requer que classes seja considerado anulável dentro do componente, forçando você a usar o operador ! ao acessar seus campos ( o compromisso atual )

Eu recomendo fortemente que, se o seu componente não tiver estado, você use um componente funcional sem estado, que exigirá menos anotações de tipo e será mais seguro para o tipo:

export default withStyles(styles)<Props>(({ classes, message }) => (
  <div className={classes.main}>
    <div className={classes.foo}>
      Hello World! {message}
    </div>
  </div>
));

Como descobri como usar StyledComponentProps ? Parece que acabei de passar strings das chaves definidas no objeto styles.

Mas os documentos nos dizem para fazer algo que simplesmente não funciona? o que estou perdendo? Eu gostaria de usar https://material-ui.com/guides/typescript/#augmenting -your-props-using-withstyles ...

Isso é possível?

@valoricDe , Como você fez o componente funcional que não tinha esse problema

@TrejGun Acabei de verificar. Com um componente funcional e @ material-ui / [email protected] eu não tenho esse problema

Estou tentando algo assim:

`` `import React, {ChangeEvent, Component, Dispatch} de" react ";
importar PropTypes de "prop-types";
importar {conectar} de "react-redux";
import {Grid, FormControlLabel, Theme, createStyles, withStyles, Radio, WithStyles} de "@ material-ui / core";
import Amount from "./Amount";
import {onPastDueFormFieldChange} de "../../store/actions/selectPaymentAmountActions";

estilos const = (tema: Tema) =>
createStyles ({
quantia: {
alignSelf: "center",
},
});

interface OwnProps estende WithStyles{}

interface StateProps {
pastDue ?: número;
pastDueOrTotalOrOther: string;
}

interface DispatchProps {
onPastDueFormFieldChange: OnPastDueFormFieldChange;
}

tipo Props = StateProps & DispatchProps & OwnProps;

const PastDueFormField = withStyles (styles) (
({classes, pastDue, pastDueOrTotalOrOther, onPastDueFormFieldChange}: Props) => (
value = "pastDue"
verificado = {pastDueOrTotalOrOther === "pastDue"}
onChange = {onPastDueFormFieldChange}
label = "Vencido:"
controle = { }
/>




),
);

const mapStateToProps = (estado: RootState): StateProps => ({
pastDue: state.customerData.balanceDue.pastDue,
pastDueOrTotalOrOther: state.customerPaymentsForm.pastDueTotalOrOther,
});

exportar conexão padrão(
mapStateToProps,
{onPastDueFormFieldChange},
) (PastDueFormField);

When I use this component I have this error:
```import PastDueFormField
Property 'classes' is missing in type '{}' but required in type 'Readonly<PropsWithChildren<Pick<Pick<Props, "pastDue" | "pastDueOrTotalOrOther" | "onPastDueFormFieldChange"> & StyledComponentProps<"amount">, "classes" | "innerRef"> & OwnProps>>'

@yehudamakarov Tente codificar sem react-redux primeiro e adicione connect quando tudo funcionar como esperado. É incrivelmente difícil obter uma boa visão geral quando o suporte é injetado.

Ao encontrar esses problemas,

  1. digite meus adereços de componente primeiro
  2. verifique se tudo é necessário conforme o esperado, ou seja, obtenha missing props
  3. aplicar hoc
  4. ver se o texto datilografado reconheceu todos os adereços injetados
  5. repita 3 até que todos os hocs sejam aplicados.

Ele promove um código mais limpo. Especialmente no que diz respeito à ordem das operações. Atualmente, você mistura withStyles e connect sem uma separação de preocupações.

Muito obrigado Sebastian.
Resolvi meu problema simplesmente não passando argumentos genéricos para conectar. Eu tirei o pedaço <StateProps ...> .

Acho que esses argumentos genéricos estavam bagunçando minha interface OwnProps que estende WithStyles <>.

Já que estou passando tudo para o componente de qualquer maneira, a verificação de tipo que obtenho de meus adereços é suficiente. Não sei por que a id precisa dos genéricos do Connect <>.

Obrigado!

Isso é o que pareceria "decorar" uma classe se tornássemos as digitações corretas:

type NonStyleProps = {
  text: string
};

const styles = {
  root: {
    backgroundColor: 'red'
  }
};

const DecoratedComponent = withStyles(styles)(
  class extends React.Component<NonStyleProps & WithStyles<'root'>> {
    render() {
      return (
        <div className={this.props.classes.root}>
          {this.props.text}
        </div>
      );
    }
  }
);

E como adicionar temas (useTheme ()) dentro, como:

const decorate = withStyles((theme: Theme) => ({
  root: {
    display: "flex"
  },
  appBar: {
    zIndex: theme.zIndex.drawer + 1,
    transition: theme.transitions.create(["width", "margin"], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen
    })
  }
})
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

reflog picture reflog  ·  3Comentários

mb-copart picture mb-copart  ·  3Comentários

ghost picture ghost  ·  3Comentários

FranBran picture FranBran  ·  3Comentários

ericraffin picture ericraffin  ·  3Comentários