26 mars 2025

Passing TypeScript React components native HTML attributes

It’s important and useful to pass native HTML element attributes onto TypeScript + React components that manage and extend them.

Here’s how: 
Take this simple input component which you can pass an isInvalid prop which adds a custom CSS class:

Screenshot of a typescript react input component. The full code is available at the sandbox link below.

Here it is being used in a React app:

Screenshot of a typescript react app rendering the custom input component. The full code is available at the sandbox link below.
Screenshot of the UI of the plain black input. The full code is available at the sandbox link below.

What happens if we want this to be a password input? Hide the value? Have a minimum length? To be required?
Do we have to add all the relevant HTML attributes for our input to CustomInputProps?
Should we create a new component?

Nope! We can use the InputHTMLAttributes interface exported from React. 


React exports a set of generic interfaces that correspond to various HTML elements.

Screenshot of the type definitions for typescript InputHTMLAttributes exported by React in the node modules

We can create a new TypeScript type which combines our custom interface and the InputHTMLAttributes interface.

Screenshot of a typescript type extending the  InputHTMLAttributes interface. The full code is available at the sandbox link below.

We can use ES6 rest operator to spread any props passed into the React Input component into the element 

Screenshot of the custom attributes being destructed in react props of the component and the rest syntax handling the other input props. The full code is available at the sandbox link below.


Now we can use all the attributes available on the input element (with no type errors).

Screenshot of the typescript component passing a native input prop into the custom input as well as custom props. The full code is available at the sandbox link below.
Screenshot of the UI of the typescript react input changed as a result of a prop change - black to red. The full code is available at the sandbox link below.

For values like className which we are passing onto the component internally, you need to handle the aggregate manually if you want to also pass a className as a prop.

Screenshot of typescript code handling the custom handling of the className prop. The full code is available at the sandbox link below.

Our final input JSX here has a mix of props typed both from the InputHTMLAttributes type and our custom type.

Screenshot of the typescript component passing a native input prop into the custom input as well as custom props. The full code is available at the sandbox link below.
Screenshot of the input which has been transformed into a password input thanks to the native HTML type=password prop. The full code is available at the sandbox link below.

Hopefully this guide helps you create more flexible, useful typesafe React components. You may use this Sandbox to play with actual code & typings demonstated in this article.

More tech articles I’ve written: