As a React developer, you’re likely familiar with the benefits of using a statically-typed language like TypeScript. TypeScript offers a type system that helps catch errors early, making it easier to write more reliable code faster. In a React context, TypeScript can also provide additional benefits such as improved code maintainability and extensibility. If you’re new to TypeScript, it’s a superset of JavaScript that adds optional static types to your code. This means that you can catch errors before your code runs, which can save you time and improve the quality of your codebase.
A common pattern in React is to create a component that takes props as an argument. TypeScript provides a utility type called ComponentProps, which automatically extracts the props type from a given component. This saves you time and helps avoid errors when defining a component’s props.
ComponentProps
proves more useful when used with rest parameters and Native HTML Elements
In this example, we’re using the ComponentProps
utility type to define the props for a custom CustomButton
component that extends the functionality of the native button element. By passing the onClick
prop to CustomButton
, we're able to handle the button click event and log a message to the console. The ...props
syntax allows us to pass any additional props to the underlying button element, such as className
or disabled
and if we tried to pass an invalid prop to the CustomButton
element, Typescript will throw an error.
Another useful TypeScript feature is the ability to use union types with useReducer
. This allows you to define a state type that can have multiple variations. For example, you can specify the type of action and the exact payload key expected
Finally, TypeScript provides a way to strongly type the functions returned by useState
. This helps ensure that you’re using the correct type when updating the state and provide better error handling.
When you use the useState
hook in a React component with TypeScript, the type of the state is inferred based on the initial value you provide. However, when you update the state using setState
, TypeScript does not perform excess property checking by default. This means that you can add additional properties to the object you pass to setState
, even if they are not part of the type of the state.
Consider the code below:
In the example above, when the Add Tag button is clicked it adds a new tag to the tags array, with properties id, value, otherValue , if the user clicked on one of the tags, the tagselected will be the tag id, there are two issues with our code, can you spot them? we added otherValue to the tags array, this property didn’t exist in our original tags type, yet typescript didn’t spot the issue. the second issue is tagselected , our original TagState interface had a property called tagSelected camel-cased, typescript didn’t spot this issue as well.
To get an error for this bug we can use explicit typing:
With explicit typing in place, TypeScript will now catch the typo in tagselected and the extra property otherValue, and throw an error. By catching these errors early, we can avoid bugs and improve the reliability of our code.
To summarize, TypeScript offers several useful features for React developers, including:
ComponentProps
utility type, which automatically extracts the props type from a given component and helps avoid errors when defining a component’s props.useReducer
.useState
functions, which helps ensure that you’re using the correct type when updating the state and catches errors early.Explicit typing with useState functions, which helps ensure that you’re using the correct type when updating the state and catches errors early.