Componentes polimórficos com a propriedade 'as'
Tipifique a propriedade 'as' para que um Button seja renderizado como ou , preservando os tipos corretos de propriedades.
Componentes polimórficos com a propriedade 'as' é uma aula grátis de React Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Academy inclui 4 aulas no total.
O que é um componente polimórfico?
Um componente polimórfico é renderizado como diferentes elementos ou componentes HTML com base em uma propriedade as — por exemplo, um Button que é renderizado como <a> ou <button>, mantendo os tipos corretos do TypeScript.
Propriedade as simples (sem TypeScript)
Uma implementação polimórfica básica sem genéricos — perde a segurança de tipos, mas demonstra o conceito.
function Box({ as: Tag = 'div', children, ...props }) {
return <Tag {...props}>{children}</Tag>;
}
// Usage:
<Box as="section" className="hero">...</Box>
<Box as="article">...</Box>Propriedade as tipada com genéricos
Adicione um parâmetro de tipo genérico para inferir as propriedades corretas para qualquer elemento que a propriedade as renderizar.
type PolymorphicProps<E extends React.ElementType> = {
as?: E;
} & Omit<React.ComponentPropsWithoutRef<E>, 'as'>;
function Box<E extends React.ElementType = 'div'>({
as,
...props
}: PolymorphicProps<E>) {
const Tag = as ?? 'div';
return <Tag {...props} />;
}Com suporte a ref
Adicione suporte a forwardRef preservando a tipagem polimórfica.
type PolymorphicRef<E extends React.ElementType> = React.ComponentPropsWithRef<E>['ref'];
type PolymorphicPropsWithRef<E extends React.ElementType, P = {}> = P &
Omit<React.ComponentPropsWithRef<E>, keyof P> & { as?: E };
const Button = React.forwardRef(
<E extends React.ElementType = 'button'>(
{ as, ...props }: PolymorphicPropsWithRef<E>,
ref: PolymorphicRef<E>
) => {
const Tag = as ?? 'button';
return <Tag ref={ref} {...props} />;
}
);Inferência do TypeScript na prática
Quando você define as='a', o TypeScript sabe que o componente aceita propriedades específicas de âncoras, como href e target, mas não propriedades específicas de botões, como disabled.
// TypeScript allows href because as='a':
<Box as="a" href="https://example.com">Link</Box>
// TypeScript errors if you pass href to a div:
<Box as="div" href="...">Error!</Box> // TS: href is not a valid div propAmpliando com propriedades personalizadas
Adicione propriedades específicas do componente junto à base polimórfica, espalhando-as na definição do tipo.
type TextProps<E extends React.ElementType> = PolymorphicProps<E> & {
size?: 'sm' | 'md' | 'lg';
weight?: 'normal' | 'bold';
};
function Text<E extends React.ElementType = 'p'>({
as,
size = 'md',
weight = 'normal',
className,
...props
}: TextProps<E>) {
const Tag = as ?? 'p';
return (
<Tag
className={[`text-${size}`, `font-${weight}`, className].filter(Boolean).join(' ')}
{...props}
/>
);
}Caso de uso real: link renderizado como RouterLink
Um Button que é renderizado como o Link do React Router quando to é fornecido, ou como um botão comum caso contrário.
import { Link } from 'react-router-dom';
type ButtonProps =
| { to: string; href?: never } & React.ComponentPropsWithoutRef<typeof Link>
| { href: string; to?: never } & React.ComponentPropsWithoutRef<'a'>
| { to?: never; href?: never } & React.ComponentPropsWithoutRef<'button'>;
function Button({ to, href, ...props }: ButtonProps) {
if (to) return <Link to={to} {...props} />;
if (href) return <a href={href} {...props} />;
return <button type="button" {...props} />;
}Componente de texto de um sistema de design
Um componente polimórfico Text que, por padrão, usa <p>, mas pode ser renderizado como h1–h6, span ou label.
<Text as="h1" size="xl">Page Title</Text>
<Text as="span" weight="bold">Inline bold</Text>
<Text as="label" htmlFor="email">Email</Text> // htmlFor is valid because as='label'Restrições da propriedade as
Use extends React.ElementType para aceitar tanto strings de elementos HTML ('div', 'a') quanto componentes React.
function Card<E extends React.ElementType = 'div'>({ as, ...props }: PolymorphicProps<E>) {
const Tag = as ?? 'div';
return <Tag {...props} />;
}
// Works with HTML elements:
<Card as="section" aria-label="Products" />
// Works with React components:
<Card as={motion.div} animate={{ opacity: 1 }} />Evitando armadilhas comuns
Não espalhe a propriedade as no elemento (ela não é um atributo HTML válido). Sempre a extraia antes de espalhar as demais propriedades.
// Bad:
function Box({ as: Tag = 'div', ...props }) {
return <Tag as={...} {...props} />; // 'as' attribute on div is invalid HTML
}
// Good:
function Box({ as: Tag = 'div', ...props }) {
return <Tag {...props} />; // 'as' is used to pick Tag, not passed to element
}Consideração de desempenho
Componentes polimórficos têm sobrecarga mínima de desempenho — a propriedade as é apenas uma variável que contém uma string de tipo de elemento ou uma referência a um componente.
Verificação rápida
Por que você deve extrair a propriedade as antes de espalhar as demais propriedades no elemento em um componente polimórfico?
Recapitulação
Componentes polimórficos usam uma propriedade genérica as?: E extends React.ElementType para renderizar qualquer elemento preservando as propriedades corretas do TypeScript. Extraia as antes de espalhar as demais propriedades. Use React.ComponentPropsWithoutRef para incluir no tipo todos os atributos específicos do elemento.
Perguntas Frequentes
A aula “Componentes polimórficos com a propriedade 'as'” é grátis?
Sim — o texto completo de “Componentes polimórficos com a propriedade 'as'” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Academy, atualize para CoddyKit PRO. O curso de React Academy inclui 4 aulas no total.
O que vou aprender em “Componentes polimórficos com a propriedade 'as'”?
Tipifique a propriedade 'as' para que um Button seja renderizado como ou , preservando os tipos corretos de propriedades. Você pratica React Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar React Academy?
Nenhuma experiência prévia é necessária. React Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Componentes polimórficos com a propriedade 'as'”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de React Academy?
Sim. Cada aula de React Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Uniões discriminadas para variantes de componentes
- Tipos condicionais e mapeados no React
- Componentes polimórficos com a propriedade 'as'
- Formulários seguros quanto aos tipos e contratos de respostas de API