Mirroring and Extending the Properties of an HTML Element
Learn how to enhance the component development by mirroring and extending the HTML element’s properties.
We'll cover the following...
Creating the Button
component
Let’s start with the first example. We want to create a button that comes with the appropriate styling for use in our application. In JavaScript, we might be able to do something like this:
const Button = (props) => {return <button className="button" {...props} />;};
In TypeScript, we will just add what we know and need. For example, we know that we need the children property if we want our custom button to behave the same way an HTML button does:
const Button = ({ children }: React.PropsWithChildren) => {return <button className="button">{children}</button>;};
We can imagine that adding properties one at a time could get a bit tiring. Instead, we can tell TypeScript that we want to match the same props that it would use for a <button>
element in React:
const Button = (props: React.ComponentProps<'button'>) => {return <button className="button" {...props} />;};
But we have a new problem. Or, rather, we had a problem that also existed in the JavaScript example and which we ignored. If someone using our new Button
component passes in a className
prop, it will override our className
. We will add some code to deal with this in a moment, but we don’t want to pass up the opportunity to show how to use a utility type in TypeScript to say, “I want to use all of the props from an HTML button except for one (or more).”
type ButtonProps = Omit<React.ComponentProps<'button'>, 'className'>;const Button = (props: ButtonProps) => {return <button className="button" {...props} />;};
Now, TypeScript will stop us or anyone else from passing a className
property into our Button
component. If we just wanted to extend the class list with whatever is passed in, we could do that in a few different ways. We could ...