# React + TypeScript: Implementing the Polymorphic Button Component

As developers, creating reusable and flexible components is a crucial aspect of building scalable applications. One powerful technique to achieve this is by developing polymorphic components.

In this article, we'll explore how to create a polymorphic component in React using TypeScript, providing a versatile solution for various scenarios.

## **Understanding Polymorphic Components**

A polymorphic component is one that can adapt its rendered element based on the context or specific requirements. In React, this flexibility is achieved by leveraging TypeScript generics. Let's dive into a practical example using a `Button` component.

## **The Code**

```typescript
import React, { ElementType, ComponentProps, PropsWithChildren } from 'react';

export type ButtonProps<AS extends ElementType> =
  PropsWithChildren<{
    as?: AS;
  }> &
    Omit<ComponentProps<AS>, 'as'>;

const Button = <AS extends ElementType>(props: ButtonProps<AS>) => {
  const {
    as: Element = 'button',
    children,
    ...attrs
  } = props;

  return (
    <Element {...attrs}>{children}</Element>
  );
};
```

The above TypeScript code defines a `ButtonProps` type, utilizing TypeScript generics to make the component polymorphic. Let's break it down:

* `AS extends ElementType`: This generic type parameter allows us to specify the element type that our button should render. It extends the `ElementType` from React, ensuring that only valid HTML elements or React components can be used.
    
* `PropsWithChildren`: This is a utility type that ensures our component can accept children.
    
* `{ as?: AS }`: The `as` prop is the key to making our component polymorphic. It allows us to specify the element type we want the button to render as. If not provided, it defaults to the standard `button` HTML element.
    
* `Omit<ComponentProps<AS>, 'as'>`: This utility type is used to exclude the `as` prop from the props of the specified element type. This is a workaround to achieve the polymorphic behaviour.
    

Breaking down the `Button` component:

* The `as` prop is destructured with a default value of `'button'`. This default ensures that if no specific element is provided, the button will render as a standard HTML button.
    
* The component then uses JSX to render the specified element, passing along the rest of the props (`...attrs`) and rendering the `children` within it.
    

## **Using the Polymorphic Button**

Now that we have our polymorphic `Button` component, let's explore how to use it in different scenarios:

### **Using as a Standard Button**

```typescript
<Button onClick={() => alert('Clicked!')}>Click me</Button>
```

### **Using as an Anchor (**`<a>`) Element

```typescript
<Button as="a" href="https://example.com">Visit Example</Button>
```

## **Conclusion**

In this article, we've explored the creation of a polymorphic `Button` component in React using TypeScript. The flexibility provided by polymorphism allows us to adapt the component to various use cases seamlessly.
