DEV Community

Mohd Ahmad
Mohd Ahmad

Posted on

Conditional types in typescript react

Here I am making a Button component which should render <button> or <a> conditionally, using the as prop. eg:-

// should render <button> component, prop 'as' is 'button' by default
<Button> Click me </Button>

// should render <a> component 
<Button as="a" href="xyz.com" > Visit here </Button>
Enter fullscreen mode Exit fullscreen mode

The code

import React, {
  AnchorHTMLAttributes,
  ButtonHTMLAttributes,
} from "react";

type Props = Partial<
  ButtonHTMLAttributes<HTMLButtonElement> &
    AnchorHTMLAttributes<HTMLAnchorElement> & { as: "a" | "button" }
>;

const Button: React.FC<Props> = ({ as: As = "a", ...rest }) => {
  return <As {...rest}></As>;
};

export default Button;
Enter fullscreen mode Exit fullscreen mode

but it is showing anchor element properties (eg: href) while as = 'button', it is not a big problem here but when I was trying to make a base component which should render as a div | main | ul | section it gives error but after removing ul it is working fine
eg

// should render <div> component 
<Base as='div' />

// should render <main> component 
<Base as='main' />

// should render <section> component 
<Base as='section' />

// should render <ul> component 
<Base as='ul' />
^ the error part as ul props and [div | main | section] props are 
not matching

Enter fullscreen mode Exit fullscreen mode

Discussion (3)

Collapse
benjioe profile image
Benjioe • Edited on

Solution, but I thinks it's not a good idea to use {...rest} because you can add href on a button and you lost autocompletion.
Maybe you have to define all manage properties (like ant's button do)

Collapse
benjioe profile image
Benjioe • Edited on

Why do you need a Base component instead of html tag ?

Collapse
zakiazfar profile image
Mohd Ahmad Author • Edited on

because I dont want to repeat myself, its like I want different element but with same props