My Refactoring Process
I needed to update the code that was written using the old style of react class components. For example, the component “SearchableText” is written using the React class component.
- Convert the code to use React functional components. Going through the process of updating the component helps me to understand the code.
- Console log the component props to confirm their types. This step can be a challenge sometimes. For example, if a component has a prop that is a > child prop passed from a parent component, then I need to track down the parent component to figure the types.
- Use command
git mv \***.js **\*.tsxto rename the file to use the
.tsxextension, which supports TypeScript. Using
git mvis important for Git to automatically detect the rename and update the history accordingly.
- Add TypeScript type annotations and Interfaces. The challenge of this step is to understand the codebase and determine the appropriate types for variables and functions. Sometimes, bugs will be revealed in the code as I add type annotations. Fixing these bugs as they crop up can be time-intensive.
- Run unit tests and update unit tests accordingly. This step helps me guarantee that the refactored code is still valid and can run successfully.
As a result, I get a React functional component that uses TypeScript. Here are the type annotations that I added. They clearly indicate the types of each prop.
What I Learned About TypeScript While Refactoring
But if we write with TypeScript support, the type error will be caught.
Using TypeScript improves code readability. Type annotations make the code more self-documenting, and I can immediately understand what types of values the function can accept and return. For example, in the following code, it’s clear that
setPageis a dispatch action.
Using TypeScript improves handling of
undefinedin the case of invalid inputs.
Using TypeScript allows me to specify the type annotations for function parameters and return values. In this case, the function is explicitly defined to return either a `number` or `null`, providing better clarity about its behavior.
TypeScript’s type system catches potential errors early in development. If I accidentally use the
resultvariable without checking for null, TypeScript would raise a compilation error.
Interfaces can define the structure of an object, specifying the properties and their types. This aids in creating contracts between different parts of the codebase and promotes code reusability.
TypeScript also can infer types based on context, even if types are not explicitly specified. This reduces the need for explicit type annotations while still providing type checking.
TypeScript supports union types (values that can be any one of multiple types) and intersection types (values that must satisfy multiple types simultaneously).
Learning Through Practical Application
It is hard to acquire new knowledge without applying what you’re learning. The refactoring process is a great opportunity to learn about TypeScript. Instead of just reading documentation and practicing using example code/code playgrounds, refactoring is a real world application. Every challenge that I encountered during refactoring was helpful to make the learning process more natural.
Technology develops fast and refactoring will keep a product alive and more competitive in terms of performance. I am a fan of refactoring not just because I personally benefit a ton from it, but also due to the benefits of having high quality code and better performing projects. Having a habit of refactoring code is a double win.
In summary, there are many ways to acquire programming knowledge, and I find my best and favorite way is through refactoring. AP is a perfect project for me to keep improving my programming skills, allowing me to enhance my knowledge during refactoring. The knowledge that I gain through refactoring is long-term knowledge, because I was able to not only learn about new topics but to apply it to the AP project.