Reputation: 46527
I am working on a button component that has variant
prop to determine it's color. Here is simplified version
interface Props extends React.HTMLProps<HTMLButtonElement> {
variant: 'yellow' | 'green';
}
function Button({ variant, ...props }: Props) {
console.log(variant);
return (
<button
type="button"
{...props}
/>
);
}
I am getting typescript error under my type
that says:
(JSX attribute) ButtonHTMLAttributes.type?: "button" | "submit" | "reset" | undefined Type 'string' is not assignable to type '"button" | "submit" | "reset" | undefined'.ts(2322) index.d.ts(1872, 9): The expected type comes from property 'type' which is declared here on type 'DetailedHTMLProps, HTMLButtonElement>'
So I am not sure if I am extending to button props correctly? Perhaps there is another way?
Upvotes: 18
Views: 22906
Reputation: 86
This is an alternative solution to this same problem, you can replace 'button'
for any html tag
import { ComponentProps } from 'react';
interface ButtonProps extends ComponentProps<'button'> {
variant: 'yellow' | 'green';
}
function Button({ variant, ...props }: ButtonProps) {
Upvotes: 2
Reputation: 2545
Update 2023
if you want to create button without any extra stuff you can extend React.ComponentPropsWithoutRef<"button">
and for people that trying to make reusable component you will need to forwardRef
the underlying element and then you can use ComponentPropsWithRef
:
interface Props extends React.ComponentPropsWithoutRef<"button"> {
variant: 'yellow' | 'green';
}
why not using React.HTMLAttributes<HTMLButtonElement>
?
this is what happens when you use:
export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
/* etc */
}
function App() {
// Property 'type' does not exist on type 'IntrinsicAttributes & ButtonProps'
return <Button type="submit"> text </Button>;
}
Old answers
what you're probably looking for is React.HTMLAttributes<HTMLButtonElement>
import * as React from "react";
import { render } from "react-dom";
import "./styles.css";
interface Props extends React.HTMLAttributes<HTMLButtonElement> {
variant: 'yellow' | 'green';
}
function Button({ variant, ...props }: Props) {
return (
<button
type="button"
{...props}
/>
);
}
const rootElement = document.getElementById("root");
render(<Button variant='green' />, rootElement);
to being more accurate we can use React.ButtonHTMLAttributes<HTMLButtonElement>
import * as React from "react";
import { render } from "react-dom";
import "./styles.css";
interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant: 'yellow' | 'green';
}
function Button({ variant, ...props }: Props) {
return (
<button
type="button"
{...props}
/>
);
}
const rootElement = document.getElementById("root");
render(<Button variant="green" />, rootElement);
Upvotes: 32
Reputation: 2284
You should use ButtonHTMLAttributes
rather than HTMLProps
like this:
interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant: 'yellow' | 'green';
}
function Button({ variant, ...props }: Props) {
console.log(variant);
return (
<button
type="button"
{...props}
/>
);
}
Upvotes: 11