How to Identify and Fix Code Smells in TypeScript using CodeRabbit

Aravind Putrevu

by Aravind Putrevu

December 19, 2024

9 min read

Cover image for article: How to Identify and Fix Code Smells in TypeScript using CodeRabbit

Integrating AI-powered code reviews in modern development workflows has fundamentally changed how development teams approach TypeScript projects.

While TypeScript's built-in features help catch errors early through static type checking, maintaining overall code quality becomes critical as codebases grow. Traditional code review processes and pair programming can slow development cycles when applied to larger teams or complex systems.

This tutorial will demonstrate how to enhance a TypeScript project by identifying code smells and improving code quality in a real-world example—a job board designed for TypeScript developers.

Let’s start by looking into what “code smells” are and why they’re important to address!

Understanding Code Smells and Why They Matter

Code smells are signs or patterns that suggest underlying issues in a code’s design or structure. While these issues may not cause immediate bugs or errors, they can lead to problems in the future, such as decreased maintainability, reduced readability, or difficulty in scaling the application. Recognizing and addressing code smells is essential for improving code quality and ensuring a more robust and efficient codebase.

Some common TypeScript code smells include long functions, duplicated code, and complex conditionals, which can affect performance and readability over time.

For any TypeScript project, identifying these early allows developers to refactor and maintain clean code. This is crucial for your application to remain scalable and maintainable as it grows.

In large projects like Slack, which uses TypeScript to grow its software, code smells can pile up over time, leading to technical debt. This can eventually affect how well the software works for users, which is bad for the business. AI tools help spot and fix these issues automatically so teams can focus on building new features faster without worrying about code quality. Let's identify common code smells in TypeScript and explore how to spot them in code snippets.

Identifying Common Code Smells in TypeScript

Here are key patterns programmers should watch for when reviewing source code:

  • Long Functions: Multiple functions or class methods handling too many responsibilities make testing and maintenance challenging.

    
      function processJobApplication(job: Job, applicant: Applicant) {
          // handles filtering, validation, notification, etc.
          // too many responsibilities in one function
        }
    
  • Duplicated Code: Repeated code fragments across multiple places indicate refactoring opportunities.

    
      function displayJobTitle(job: Job) {
          console.log(job.title);
        }
    
        function showJobTitle(job: Job) {
          console.log(job.title);
        }
    
  • Complex Conditionals: Nested or complicated conditions can make code difficult to understand and debug.

    
      if (job.salary > 50000 && job.location === 'remote' && job.type === 'full-time') {
          // complex logic that could be simplified
        }
    

Manual code reviews can be time-consuming when dealing with large codebases, especially when identifying and addressing code smells such as in-functions for filtering jobs or displaying job details.

Using a TypeScript job board project, the section below will demonstrate how AI-powered code review tools can automatically detect and flag these issues, making it easier to refactor your code efficiently.

Setting up the TypeScript Job Board

This tutorial will walk you through creating a job board application where you'll implement type-safe features and use an AI-powered code review tool to catch potential issues.

Prerequisites

You must have the following to get started:

  • Familiarity with TypeScript, React, or Next.js.

  • Node.js, npm installed.

  • Shadcn UI installed

  • CodeRabbit account.

  • VS Code (or another code editor).

To set up the job board quickly, clone the repository from GitHub, install dependencies, and run the app locally with the commands below:

  1. Clone the repository:

     git clone https://github.com/Tabintel/typescript-job-board.git
    
  2. Install dependencies:

     cd typescript-job-board
     npm install
    
  3. Run the application:

     npm run dev
    
  4. Open localhost:3000 in your browser to view the TypeScript job board:

    TypeScript job board built with Next.js and TypeScript

The job board is designed to help TypeScript developers find job opportunities. It includes a sidebar for filtering jobs, dynamically generated job cards, and a responsive layout. With the application up and running, let’s focus on how AI code review tools like CodeRabbit can help us catch and address code smells.

Setting up AI-Powered Code Review

Create an account and follow the integration guidelines in the documentation to integrate AI into your workflow. Once installed, you can start utilizing AI to streamline code reviews and maintain high-quality standards in your TypeScript projects.

To activate the review process, create a branch on your repository, make code updates, push, and initiate a pull request (PR).

Let’s create a new feature for the job board application by running the command below in the terminal:

git checkout -b feature/job-application-form

This feature will allow TypeScript developers using the job board to apply for jobs directly through the platform. The components include:

  • TypeScript interfaces for form data validation.

  • Strongly typed form handling with React state management.

  • Type-safe event handlers for form submissions.

Next, create a JobApplicationForm component in the src/app/components/ directory and enter the code from this GitHub gist.

Once you've added the code, commit and push the changes to your GitHub repository using the following commands:


git add src/components/JobApplicationForm.tsx
git commit -m "feat: add job application form with TypeScript"
git push origin feature/job-application-form

Then, navigate to your GitHub repository, where you’ll see a prompt to create a pull request from the new branch.

Create the pull request (PR) with a descriptive title and description of the new feature.

Create a Pull Request

The pull request triggers an AI-powered code review process, analyzing the source code for potential code smells and areas needing refactoring.

CodeRabbit review process

Analysis and Review of the Code Smells

After creating the PR, AI-powered code review tools automatically analyze your code, identify several issues, and add a nice poem for the job board, as indicated in the image:

CodeRabbit’s walkthrough for the code review

It suggests code that can be refactored to fix the code smell, as shown below:

Code smells highlighted by CodeRabbit

It also highlights code smells in the TypeScript code that are potential issues:

Other code smells in the TypeScript code

Let's break down the code smells found in JobApplicationForm.tsx by looking at the original code and also reviewing the improvements and suggestions from the automated review.

Inadequate State Management

The existing code shows common code smells in state management. Without clear loading indicators and error-handling states, users are left without feedback during form submissions, which can result in a confusing user experience. AI code review tools help identify and suggest strategies to address such gaps.

State management code smell spotted by CodeRabbit with suggestions

The solution from the AI code review introduces comprehensive state management with loading and error states. The isSubmitting flag enables proper loading indicators, while the error state allows for meaningful error messages. The default TypeScript experience is set to one year, providing job applicants with a more realistic starting point.


// CodeRabbit's Improved Solution
const [isSubmitting, setIsSubmitting] = useState(false)
const [error, setError] = useState<string | null>(null)
const [application, setApplication] = useState<JobApplication>({
  position: '',
  yearsOfTypeScript: 1,  // Better default value
  githubProfile: '',
  email: '',
  portfolioUrl: ''
})

Missing Error States

From the review below, the form submission handler lacks proper error handling and doesn't manage the submission lifecycle. This can lead to silent failures and provide no feedback to users when something goes wrong.

Error handling code smell spotted by CodeRabbit

The improved submission handler implements a proper async/await pattern with comprehensive error handling. It manages the entire submission lifecycle, from setting loading states to handling errors and success cases, making sure users always know the status of their submission.


const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault()
  try {
    setIsSubmitting(true)
    setError(null)
    await submitApplication(application)
    // Show success message
  } catch (err) {
    setError(err instanceof Error ? err.message : 'Submission failed')
  } finally {
    setIsSubmitting(false)
  }
}

Untyped Promise Response

The use of any type in Promise returns can hinder TypeScript’s type safety and reduce clarity for other developers. Implementing strongly typed return values and input validation is a recommended approach.

Untyped promise response code smell spotted by CodeRabbit

The automated code review tool implements proper typing for the Promise return value and adds input validation. This maintains type safety throughout the application flow and provides clear feedback for validation errors.


const submitApplication = (data: JobApplication) => {
  return new Promise<{ success: boolean; message?: string }>((resolve, reject) => {
    if (!data.email.includes('@')) {
      reject(new Error('Invalid email format'))
      return
    }
    resolve({ success: true, message: 'Application submitted successfully' })
  })
}

Poor Accessibility

The form lacks proper accessibility attributes, making it difficult for screen readers to provide meaningful information to users with special needs.

Poor Accessibility code smell spotted by CodeRabbit

The enhanced form includes proper ARIA attributes and roles, making it accessible to screen readers and assistive technologies. The noValidate attribute allows for custom form validation while maintaining accessibility.


<form 
  onSubmit={handleSubmit} 
  className="space-y-4 w-full max-w-md"
  aria-label="Job Application Form"
  noValidate
>
  <input
    type="email"
    id="email"
    aria-invalid={!!emailError}
    aria-describedby="email-error"
    required
  />
</form>

Through this automated code review process, you’ve learned valuable lessons about TypeScript development. Proper type definitions serve as both documentation and runtime safeguards. Error handling becomes more predictable when properly typed, and accessibility features become natural parts of the development process rather than afterthoughts.

Continuously Improving Code Quality with AI Code Reviews

Incorporating AI-powered code review tools brings lasting improvements to your development process. Here's how it helps improve both your source code quality and overall development efficiency:

  • Efficient Development: With automated code review tools continuously identifying code smells during development, programmers can focus on building better software features while reducing time spent on manual code reviews and pair programming sessions.

  • Technical Debt Prevention: By detecting and addressing code smells early, development teams prevent deeper problems from escalating into complex issues. This proactive approach to code cleaner practices ensures maintainable codebases across multiple functions and class methods.

  • Enhanced Code Quality: Clean, organized source code with proper type information minimizes bugs and errors. The systematic use of primitive types and type inference makes scaling easier, allowing open-source projects to evolve smoothly as new functionality is added.

What’s Next?

Now that you have learned how to identify and address code smells in TypeScript using AI-powered code review, here are some additional considerations and next steps to enhance your development process:

  1. Refining TypeScript Practices: As you continue to improve your codebase, it’s helpful to focus on enhancing your use of TypeScript’s more advanced features, such as generics and type inference. These can lead to better maintainability and fewer runtime errors.

  2. Integrating AI with Human Insights: While AI code review tools like CodeRabbit are powerful, they should be balanced with human insights. Encourage team members to review AI-generated feedback and provide their perspectives to build a learning and continuous improvement culture.

  3. Staying Up to Date: TypeScript constantly evolves with new features and updates. Monitor the latest changes, such as stricter types or improved tooling, to incorporate better practices and avoid potential pitfalls.

Final Thought

AI tools empower developers to analyze TypeScript (or other programming languages) source code, identify common code smell patterns, and implement refactoring opportunities that elevate code quality standards. The development workflow becomes faster and more efficient, enabling teams to ship software confidently.

Ready to enhance your TypeScript projects with better software practices? Sign up for CodeRabbit today and experience the benefits of AI-powered code reviews.

pill

Still have questions?

Contact us