Criando componentes polimórficos com React e TypeScript
Adicionar polimorfismo aos seus componentes React os tornará mais versáteis, pois os consumidores poderão definir o elemento renderizado ao arquivo DOM.
Há etapas importantes a serem seguidas ao construir esses componentes, então vamos começar!
Por que precisamos de componentes polimórficos?
Você deve ter notado que em algumas bibliotecas como ( Material UI ou Chakra UI ) alguns componentes têm a opção de permitir um asou elementTypeprop. Isso é importante para personalização, mas também para melhorar a acessibilidade, permitindo-nos usar elementos semânticos HTML ao renderizar nossos componentes.
Adicionando um asprop a um componente React
Vamos ver como poderíamos implementar algo semelhante a essas bibliotecas — começaremos com um Textcomponente React simples.
const Text = ({ as, children, ...rest }) => {
const Component = as || "span";
return <Component {...rest}>{children}</Component>;
};
export default function App() {
return <Text>Text goes here</Text>; // Will render a span by default
}
<Text as="main">Text goes here</Text>;
<Text as="p">Text goes here</Text>;
<Text as="section">Text goes here</Text>;
<Text as="a" href="www.example.com">Text goes here</Text>
Funciona como um encanto! Ah, mas espera…
<Text as="p" href="www.example.com">
Text goes here
</Text>
Aí vem o TypeScript
É aqui que entra nosso melhor amigo TypeScript.
Precisamos garantir que as Textprops do componente sejam fortemente tipadas para que possam ser verificadas estaticamente durante o processo de desenvolvimento.
O plano é permitir que nossa asprop aceite qualquer elemento HTML válido e, de alguma forma, determine quais atributos HTML são válidos com base nesse mesmo elemento (por exemplo, uma atag deve permitir o hrefatributo).
Criando nossos tipos
Vamos começar configurando um tipo para o asprop.
import { ElementType } from "react";
type AsProp<T extends ElementType> = {
/**
* The HTML element used for the root node.
*/
as?: T;
};
Nosso tipo Té restrito a tipos que se estendem ElementTypede React, ou seja, quaisquer elementos HTML válidos.
import { ComponentPropsWithoutRef } from "react";
ComponentPropsWithoutRef<T>
Omit<ComponentPropsWithoutRef<T>, keyof Props<T>>
Props<T> & Omit<ComponentPropsWithoutRef<T>, keyof Props<T>>
Nossos tipos combinados devem se parecer com isto:
type TextProps<T extends ElementType> = PropsWithChildren<AsProp<T>> &
Omit<ComponentPropsWithoutRef<T>, keyof AsProp<T>>;
Finalmente TextPropstem tudo o que precisamos Text! Vamos juntar tudo e adicionar o tipo ao nosso Textcomponente:
import {
ElementType,
ComponentPropsWithoutRef,
PropsWithChildren
} from "react";
type AsProp<T extends ElementType> = {
/**
* The HTML element used for the root node.
*/
as?: T;
};
type TextProps<T extends ElementType> = PropsWithChildren<AsProp<T>> &
Omit<ComponentPropsWithoutRef<T>, keyof AsProp<T>>;
const Text = <T extends ElementType = "span">({
as,
children,
...rest
}: TextProps<T>) => {
const Component = as || "span";
return <Component {...rest}>{children}</Component>;
};
A melhor coisa sobre nossa configuração é que agora ...resttambém é fortemente tipado.
Então isso deve funcionar:
<Text as="a" href="www.google.com">
Text goes here
</Text>
<Text as="main" href="www.google.com">
Text goes here
</Text>





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)