Pesquisa de site

reactjs - React com Typescript: Acessar tipos de propriedades de componentes


O pacote npm @types/react nos permite usar React dentro de nossos aplicativos TypeScript. Definimos componentes como

type Props = {...}

type State = {...}

export default class MyComponent extends React.Component<Props, State> {
}

aqui precisamos declarar tipos para as props e o estado do componente (em variáveis de tipo).

Depois que declaramos esses tipos, o TypeScript os usa para validar o uso do nosso componente (a forma das props passadas para ele).

Quero criar um contêiner em torno de tal componente. O contêiner irá reutilizar os props do componente. Mas, para criar outro componente com os mesmos props, tenho que declarar novamente os tipos de props. Ou exportá-los do arquivo do componente original e importar para o contêiner:

// original file
export type Props = {...}

// container file
import MyComponent, { Props } from './original'

Mas eu já estou importando o MyComponent desse arquivo. Este componente já contém informações sobre as props que ele consome (graças às variáveis de tipo em React.Component).

A questão é como eu acesso essa informação a partir da própria classe do componente sem exportar/importar explicitamente o tipo para as props?

Eu quero algo como:

import MyComponent from './MyComponent'

type Props = MyComponent.Props // <= here access the component prop types

export default class MyContainer extends React.Component<Props, {}> {}

Resposta #1

2019: percebi que todas as respostas acima estão bastante desatualizadas, então aqui está uma nova.

Tipo de pesquisa

Com as versões mais recentes do TS, você pode usar tipos de pesquisa.

type ViewProps = View['props']

Apesar de ser muito conveniente, isso só funcionará com componentes de classe.

React.ComponentProps

Os typedefs do React vêm com uma utilidade para extrair o tipo das props de qualquer componente.

type ViewProps = React.ComponentProps<typeof View>

type InputProps = React.ComponentProps<'input'>

Isso é um pouco mais detalhado, mas ao contrário da solução de busca por tipo:

  • a intenção do desenvolvedor está mais clara
  • isso funcionará tanto com componentes funcionais quanto com componentes de classe

Tudo isso torna esta solução a mais à prova de futuro: se você decidir migrar de classes para hooks, não precisará refatorar nenhum código do cliente.

Resposta #2

A partir do TypeScript 2.8, você pode usar tipos condicionais, por exemplo, dado:

interface MyComponentProps { bar: string; }
declare const MyComponent: React.Component<MyComponentProps>;

interface MyComponentClassProps { bar: string; }
declare const MyComponentClass: React.ComponentClass<MyComponentClassProps>;

interface MyStatelessComponentProps { bar: string; }
declare const MyStatelessComponent: React.StatelessComponent<MyStatelessComponentProps>;

Podemos definir esses auxiliares:

type GetComponentProps<T> = T extends React.ComponentType<infer P> | React.Component<infer P> ? P : never

E use-os assim:

// $ExpectType MyComponentProps
type MyComponentPropsExtracted = GetComponentProps<typeof MyComponent>

// $ExpectType MyComponentClassProps
type MyComponentClassPropsExtracted = GetComponentProps<typeof MyComponentClass>

// $ExpectType MyStatelessComponentProps
type MyStatelessComponentPropsExtracted = GetComponentProps<typeof MyStatelessComponent>

Atualização 2018-12-31: isso agora está disponível nas tipagens oficiais do React via React.ComponentProps.

Artigos relacionados