How to Convert React Component to TypeScript

If you have been building React applications for a while, you know that JavaScript is incredibly flexible. However, that flexibility often leads to “undefined is not a function” errors right when you least expect them.

I have spent over eight years architecting React apps, and I can tell you from experience that moving to TypeScript was the best decision for my team’s productivity. It catches bugs before you even hit ‘save.’

In this tutorial, I will show you exactly how to convert your React components to TypeScript. We will move past the basic “Hello World” and use a real-world scenario: a Sales Tax Calculator for US-based e-commerce.

Why You Should Convert to TypeScript

When I first started with React, Proptypes were the go-to for validation. While they helped, they only caught errors at runtime, which is often too late.

TypeScript provides static typing. This means your editor will tell you immediately if you are passing a string where a number should be, saving you hours of debugging.

In a large codebase, this acts as “living documentation.” You don’t have to guess what shape an object is; the type definition tells you exactly what to expect.

Method 1: Convert a Simple Functional Component

The most common task is converting a standard functional component. I usually start by changing the file extension from .jsx to .tsx.

Let’s look at a component that calculates the final price of an item, including state tax in California (currently 7.25%).

The JavaScript Version:

import React from 'react';

const SalesTaxUtility = ({ productName, price, quantity }) => {
  const taxRate = 0.0725;
  const total = (price * quantity) * (1 + taxRate);

  return (
    <div className="tax-container">
      <h3>Invoice for {productName}</h3>
      <p>Quantity: {quantity}</p>
      <p>Total (including CA Tax): ${total.toFixed(2)}</p>
    </div>
  );
};

export default SalesTaxUtility;

You can see the output in the screenshot below.

React Component to TypeScript

The TypeScript Version: To convert this, I define an interface for the props. This is the cleanest way to handle component signatures.

import React from 'react';

// I define the structure of the props here
interface SalesTaxProps {
  productName: string;
  price: number;
  quantity: number;
}

// I use React.FC (Functional Component) to type the component
const SalesTaxUtility: React.FC<SalesTaxProps> = ({ productName, price, quantity }) => {
  const taxRate: number = 0.0725;
  const total: number = (price * quantity) * (1 + taxRate);

  return (
    <div className="tax-container" style={{ padding: '20px', border: '1px solid #ccc' }}>
      <h3>Invoice for {productName}</h3>
      <p>Unit Price: ${price.toFixed(2)}</p>
      <p>Quantity: {quantity}</p>
      <p><strong>Total (including CA Tax): ${total.toFixed(2)}</strong></p>
    </div>
  );
};

export default SalesTaxUtility;

In this example, if someone tries to pass a string for the price, the code simply won’t compile. This level of safety is vital for financial applications.

Method 2: Handle State with the useState Hook

Managing state is where things get interesting. In many cases, TypeScript can infer the type of your state based on the initial value.

However, when dealing with complex objects like US shipping addresses, you need to be explicit.

The TypeScript Implementation:

import React, { useState } from 'react';

interface ShippingAddress {
  street: string;
  city: string;
  state: string;
  zipCode: string;
}

const AddressManager: React.FC = () => {
  // I initialize the state with a ShippingAddress type
  const [address, setAddress] = useState<ShippingAddress>({
    street: '1600 Pennsylvania Avenue NW',
    city: 'Washington',
    state: 'DC',
    zipCode: '20500'
  });

  const updateZip = (newZip: string) => {
    setAddress({ ...address, zipCode: newZip });
  };

  return (
    <div>
      <h2>Shipping Department</h2>
      <p>{address.street}</p>
      <p>{address.city}, {address.state} {address.zipCode}</p>
      <button onClick={() => updateZip('20001')}>Update to Local Hub</button>
    </div>
  );
};

export default AddressManager;

You can see the output in the screenshot below.

Convert React Component to TypeScript

Using the <ShippingAddress> syntax tells TypeScript that this state will always follow that specific structure. This prevents me from accidentally adding a field like country if it isn’t in my interface.

Method 3: Handle Form Events and Inputs

One of the trickiest parts of converting to TypeScript is typing events. I often see developers use any, but that defeats the purpose of the language.

When building a login form for a corporate portal, you want to ensure the event types are strictly defined.

The TypeScript Implementation:

import React, { useState, ChangeEvent, FormEvent } from 'react';

const EmployeeLogin: React.FC = () => {
  const [email, setEmail] = useState<string>('');

  // I use ChangeEvent with HTMLInputElement for the target
  const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
    setEmail(e.target.value);
  };

  // I use FormEvent for the form submission
  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    console.log(`Authenticating user: ${email}`);
    // Logic for US-based SSO integration would go here
  };

  return (
    <form onSubmit={handleSubmit} style={{ marginTop: '20px' }}>
      <label htmlFor="email">Corporate Email:</label>
      <input 
        id="email"
        type="email" 
        value={email} 
        onChange={handleInputChange} 
        placeholder="user@company.us"
      />
      <button type="submit">Access Secure Portal</button>
    </form>
  );
};

export default EmployeeLogin;

You can see the output in the screenshot below.

How to Convert React Component to TypeScript

By using ChangeEvent<HTMLInputElement>, I get full autocompletion for e.target.value. This is a huge time saver when you are building long forms.

Method 4: Convert Class-Based Components

While functional components are the standard today, you might still encounter legacy class components in older US enterprise systems.

I have found that converting these requires a slightly different approach using generic types.

The TypeScript Implementation:

import React, { Component } from 'react';

interface PayrollProps {
  employeeName: string;
  hourlyRate: number;
}

interface PayrollState {
  hoursWorked: number;
  isPaid: boolean;
}

// I pass the Props and State interfaces as generics
class PayrollCalculator extends Component<PayrollProps, PayrollState> {
  constructor(props: PayrollProps) {
    super(props);
    this.state = {
      hoursWorked: 40,
      isPaid: false
    };
  }

  processPayment = (): void => {
    this.setState({ isPaid: true });
    alert(`Payment processed for ${this.props.employeeName}`);
  };

  render() {
    const grossPay = this.props.hourlyRate * this.state.hoursWorked;

    return (
      <div className="payroll-card">
        <h2>Payroll: {this.props.employeeName}</h2>
        <p>Gross Pay (Weekly): ${grossPay.toLocaleString('en-US')}</p>
        <button onClick={this.processPayment} disabled={this.state.isPaid}>
          {this.state.isPaid ? 'Paid' : 'Issue Paycheck'}
        </button>
      </div>
    );
  }
}

export default PayrollCalculator;

In class components, Component<PayrollProps, PayrollState> ensures that both this.props and this.state are strictly typed throughout the class.

Best Practices for Migration

When I migrate a project, I don’t try to do everything at once. I start by enabling allowJs in the tsconfig.json file.

This allows me to have a mix of .js and .tsx files. I usually convert the smallest, most reused components first, like buttons or input fields.

I also avoid using any at all costs. If I am unsure of a type, I use unknown or try to define a partial interface. This keeps the integrity of the type system intact.

Useful Tips for TypeScript in React

  • Use Type Shortcuts: You can use React.InputHTMLAttributes<HTMLInputElement> to quickly get all standard HTML props for an input.
  • Optional Props: Use the ? symbol in your interface (e.g., middleName?: string) for fields that aren’t required.
  • External Libraries: Many US-based libraries have types available via @types/ on NPM. Always check there first.

Converting your React components to TypeScript is one of the best ways to ensure your application is scalable and maintainable. It might feel like extra work initially, but the reduction in bugs is worth the effort.

In this tutorial, I have covered several ways to convert your components, from simple functional ones to state management and class-based structures.

You may also like to read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.