Convert Figma logo to code with AI

microsoft logoTypeScript-React-Conversion-Guide

A guide for converting a simple JavaScript/React project to TypeScript. Contains both before an after code with the step-by-step process in the README below.

1,428
202
1,428
10

Top Related Projects

Set up a modern web app by running one command.

44,903

Cheatsheets for experienced React developers getting started with TypeScript

The complete guide to static typing in "React & Redux" apps using TypeScript

44,901

Cheatsheets for experienced React developers getting started with TypeScript

The repository for high quality TypeScript type definitions.

Quick Overview

The TypeScript-React-Conversion-Guide is a comprehensive resource provided by Microsoft to help developers migrate their React projects from JavaScript to TypeScript. It offers step-by-step instructions, best practices, and common pitfalls to avoid during the conversion process.

Pros

  • Detailed and well-structured guide for converting React projects to TypeScript
  • Officially maintained by Microsoft, ensuring up-to-date and reliable information
  • Includes practical examples and solutions for common conversion challenges
  • Covers both basic and advanced TypeScript concepts in the context of React development

Cons

  • May not cover all edge cases or specific project configurations
  • Could be overwhelming for beginners new to TypeScript or React
  • Requires regular updates to keep pace with evolving TypeScript and React ecosystems
  • Focuses primarily on conversion rather than building new projects from scratch with TypeScript

Code Examples

This repository is a guide and does not contain a code library. Therefore, code examples are not applicable in this context.

Getting Started

As this is a guide and not a code library, there are no specific getting started instructions. However, to begin using the guide:

  1. Visit the repository at https://github.com/microsoft/TypeScript-React-Conversion-Guide
  2. Read through the README.md file for an overview of the guide's contents
  3. Navigate through the various sections of the guide, starting with the basics and progressing to more advanced topics
  4. Follow along with the examples and instructions provided to convert your React project to TypeScript

Competitor Comparisons

Set up a modern web app by running one command.

Pros of Create React App

  • Provides a complete, production-ready setup for React applications
  • Includes built-in support for modern JavaScript features and CSS preprocessing
  • Offers a smooth development experience with hot reloading and error reporting

Cons of Create React App

  • Less flexible for customizing the build configuration
  • Larger bundle size due to included dependencies
  • May require ejecting to access advanced configuration options

Code Comparison

TypeScript-React-Conversion-Guide:

import React from 'react';

interface Props {
  name: string;
}

const Greeting: React.FC<Props> = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

Create React App:

import React from 'react';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <p>Edit <code>src/App.js</code> and save to reload.</p>
      </header>
    </div>
  );
}

The TypeScript-React-Conversion-Guide focuses on TypeScript integration with React, while Create React App provides a complete JavaScript-based React setup. The former offers more type safety and better IDE support, while the latter emphasizes rapid development and ease of use for JavaScript developers.

44,903

Cheatsheets for experienced React developers getting started with TypeScript

Pros of React TypeScript Cheatsheets

  • More comprehensive and regularly updated content
  • Community-driven with contributions from various developers
  • Includes advanced TypeScript patterns and best practices for React

Cons of React TypeScript Cheatsheets

  • May be overwhelming for beginners due to its extensive content
  • Less structured approach compared to a step-by-step guide
  • Requires more time to navigate and find specific information

Code Comparison

TypeScript-React-Conversion-Guide:

interface Props {
  name: string;
}

const Greeting: React.FC<Props> = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

React TypeScript Cheatsheets:

type Props = {
  name: string;
  age?: number;
};

const Greeting = ({ name, age }: Props): JSX.Element => {
  return <h1>Hello, {name}! {age && `You are ${age} years old.`}</h1>;
};

The React TypeScript Cheatsheets example demonstrates more advanced TypeScript usage, including optional properties and conditional rendering. It also uses the more flexible type instead of interface and explicitly declares the return type as JSX.Element rather than relying on the React.FC type.

The complete guide to static typing in "React & Redux" apps using TypeScript

Pros of react-redux-typescript-guide

  • More comprehensive coverage of React, Redux, and TypeScript integration
  • Regularly updated with the latest best practices and patterns
  • Includes advanced topics like performance optimizations and testing

Cons of react-redux-typescript-guide

  • May be overwhelming for beginners due to its extensive content
  • Focuses primarily on Redux, which might not be necessary for all React projects

Code Comparison

TypeScript-React-Conversion-Guide:

interface Props {
  name: string;
}

const Greeting: React.FC<Props> = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

react-redux-typescript-guide:

type Props = {
  name: string;
};

const Greeting: React.FC<Props> = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

Summary

While both repositories aim to help developers use TypeScript with React, react-redux-typescript-guide offers a more in-depth exploration of the ecosystem, including Redux integration. It's better suited for developers working on complex applications or those seeking advanced techniques. On the other hand, TypeScript-React-Conversion-Guide provides a more focused approach to converting existing React projects to TypeScript, which may be more accessible for beginners or those specifically looking to migrate their codebase.

44,901

Cheatsheets for experienced React developers getting started with TypeScript

Pros of React TypeScript Cheatsheets

  • More comprehensive and regularly updated content
  • Community-driven with contributions from various developers
  • Includes advanced TypeScript patterns and best practices for React

Cons of React TypeScript Cheatsheets

  • May be overwhelming for beginners due to its extensive content
  • Less structured approach compared to a step-by-step guide
  • Requires more time to navigate and find specific information

Code Comparison

TypeScript-React-Conversion-Guide:

interface Props {
  name: string;
}

const Greeting: React.FC<Props> = ({ name }) => {
  return <h1>Hello, {name}!</h1>;
};

React TypeScript Cheatsheets:

type Props = {
  name: string;
  age?: number;
};

const Greeting = ({ name, age }: Props): JSX.Element => {
  return <h1>Hello, {name}! {age && `You are ${age} years old.`}</h1>;
};

The React TypeScript Cheatsheets example demonstrates more advanced TypeScript usage, including optional properties and conditional rendering. It also uses the more flexible type instead of interface and explicitly declares the return type as JSX.Element rather than relying on the React.FC type.

The repository for high quality TypeScript type definitions.

Pros of DefinitelyTyped

  • Extensive collection of type definitions for numerous JavaScript libraries
  • Community-driven project with frequent updates and contributions
  • Supports a wide range of JavaScript ecosystems beyond React

Cons of DefinitelyTyped

  • Can be overwhelming due to its large scope and numerous type definitions
  • May require more setup and configuration for specific project needs
  • Type definitions might not always be up-to-date with the latest library versions

Code Comparison

TypeScript-React-Conversion-Guide example:

interface Props {
  name: string;
  age: number;
}

const Greeting: React.FC<Props> = ({ name, age }) => {
  return <h1>Hello, {name}! You are {age} years old.</h1>;
};

DefinitelyTyped example (React type definition):

declare namespace React {
  interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> { }
  
  type FC<P = {}> = FunctionComponent<P>;
  
  interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
    propTypes?: WeakValidationMap<P> | undefined;
    contextTypes?: ValidationMap<any> | undefined;
    defaultProps?: Partial<P> | undefined;
    displayName?: string | undefined;
  }
}

The TypeScript-React-Conversion-Guide focuses on practical examples for converting React projects to TypeScript, while DefinitelyTyped provides comprehensive type definitions for various libraries, including React.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

TypeScript React Conversion Guide

This walkthrough illustrates how to adopt TypeScript in an existing React/Babel/Webpack project. We'll start with a TicTacToe project written fully in JavaScript in the TicTacToe_JS folder as an example. By the end, you will have a TicTacToe project fully written with TypeScript.

If you are starting a new React project instead of converting one, you can use this tutorial.

Adopting TypeScript in any project can be broken down into 2 phases:

  • Adding the TypeScript compiler (tsc) to your build pipeline.
  • Converting JavaScript files into TypeScript files.

Understand the existing JavaScript project

Before we dive into TypeScript adoption, let's take a look at the structure of the TicTacToe app -- it contains a few components and looks like the below (with or without TypeScript).

As shown in package.json, the app already includes React/ReactDOM, Webpack as the bundler & task runner, and the babel-loader Webpack plugin to use Babel for ES6 and JSX transpilation. The project initially has the below overall layout before we adopt TypeScript:

TicTacToe_JS /
    |---- css/			              // css style sheets
    |---- src/			              // source files
        |---- app.jsx		          // the App React component
        |---- board.jsx		        // the TicTacToe Board React component
        |---- constants.js		    // some shared constants
        |---- gameStateBar.jsx	  // GameStatusBar React component
        |---- restartBtn.jsx	    // RestartBtn React component
    |---- .babelrc		            // a list of babel presets
    |---- index.html		          // web page for our app
    |---- package.json		        // node package configuration file
    |---- webpack.config.js	      // Webpack configuration file

Add TypeScript compiler to build pipeline

Install dependencies

To get started, open a terminal and cd to the TicTacToe_JS folder. Install all dependencies defined in package.json.

cd TicTacToe_JS
npm install

Additionally, install TypeScript (3 or higher), ts-loader and source-map-loader as dev dependencies if you haven't. ts-loader is a Webpack plugin that helps you compile TypeScript code to JavaScript, much like babel-loader for Babel. There are also other alternative loaders for TypeScript! Source-map-loader adds source map support for debugging.

npm install --save-dev typescript ts-loader source-map-loader

Get the type declaration files (.d.ts files) from @types for any library in use. For this project, we have React and ReactDOM.

npm install --save @types/react @types/react-dom

If you are using an older version of React or ReacDOM that is incompatible with the latest .d.ts files from @types, you can specify a version number for @types/react or @types/react-dom in package.json.

Configure TypeScript

Next, configure TypeScript by creating a tsconfig.json file in the TicTacToe_JS folder, and add:

{
    "compilerOptions": {
        "outDir": "./dist/",        // path to output directory
        "sourceMap": true,          // allow sourcemap support
        "strictNullChecks": true,   // enable strict null checks as a best practice
        "module": "es6",            // specify module code generation
        "jsx": "react",             // use typescript to transpile jsx to js
        "target": "es5",            // specify ECMAScript target version
        "allowJs": true             // allow a partial TypeScript and JavaScript codebase

    },
    "include": [
        "./src/"
    ]
}

You can edit some of the options or add more based on your project's requirements. See more options in the full list of compiler options.

Set up build pipeline

To add TypeScript compilation as part of our build process, you need to modify the Webpack config file webpack.config.js. This section is specific to Webpack. However, if you are using a different task runner (e.g. Gulp) for your React/Babel project, the idea is the same - replace the Babel build step with TypeScript, as TypeScript also offers transpiling to lower ECMAScript versions and JSX transpilation with a shorter build time in most cases. If you wish, you can also keep Babel by adding a TypeScript build step before Babel and feeding its output to Babel.

Generally, we need to change webpack.config.js in a few ways:

  1. Expand the module resolution extensions to include .ts and .tsx files.
  2. Replace babel-loader with ts-loader.
  3. Add source-map support.

Let's modify webpack.config.js with the below:

module.exports = {
  // change to .tsx if necessary
  entry: './src/app.jsx',
  output: {
    filename: './bundle.js'
  },
  resolve: {
    // changed from extensions: [".js", ".jsx"]
    extensions: [".ts", ".tsx", ".js", ".jsx"]
  },
  module: {
    rules: [
      // changed from { test: /\.jsx?$/, use: { loader: 'babel-loader' }, exclude: /node_modules/ },
      { test: /\.(t|j)sx?$/, use: { loader: 'ts-loader' }, exclude: /node_modules/ },

      // addition - add source-map support
      { enforce: "pre", test: /\.js$/, exclude: /node_modules/, loader: "source-map-loader" }
    ]
  },
  externals: {
    "react": "React",
    "react-dom": "ReactDOM",
  },
  // addition - add source-map support
  devtool: "source-map"
}

You can delete .babelrc and all Babel dependencies from package.json if you no longer need them.

Note that if you plan to adopt TypeScript in the entry file, you should change entry: './src/app.jsx', to entry: './src/app.tsx', as well. For the time being, we will keep it as app.jsx.

You now have the build pipeline correctly set up with TypeScript handling the transpilation. Try bundling the app with the following command and then open index.html in a browser:

npx webpack

We are assuming you are using npx addition for npm to execute npm packages directly

Transition from JS(X) to TS(X)

In this part, we will walk through the following steps progressively,

  1. The minimum steps of converting one module to TypeScript.
  2. Adding types in one module to get richer type checking.
  3. Fully adopting TypeScript in the entire codebase.

While you get the most out of TypeScript by fully adopting it across your codebase, understanding each of the three steps comes in handy as you decide what to do in case you have certain part of your JavaScript codebase you want to leave as-is (think legacy code that no one understands).

Minimum transition steps

Let's look at gameStateBar.jsx as an example.

Step one is to rename gameStateBar.jsx to gameStateBar.tsx. If you are using any editor with TypeScript support such as Visual Studio Code, you should be able to see a few complaints from your editor.

On line 1 import React from "react";, change the import statement to import * as React from "react". This is because while importing a CommonJS module, Babel assumes modules.export as default export, while TypeScript does not.

On line 3 export class GameStateBar extends React.Component {, change the class declaration to export class GameStateBar extends React.Component<any, any> {. The type declaration of React.Component uses generic types and requires providing the types for the property and state object for the component. The use of any allows us to pass in any value as the property or state object, which is not useful in terms of type checking but suffices as minimum effort to appease the compiler.

By now, ts-loader should be able to successfully compile this TypeScript component to JavaScript. Again, try bundling the app with the following command and then open index.html in a browser,

npx webpack

Add types

The more type information provided to TypeScript, the more powerful its type checking is. As a best practice, we recommend providing types for all declarations. We will again use the gameStateBar component as an example.

For any React.Component, we should properly define the types of the property and state object. The gameStateBar component has no properties, therefore we can use {} as type.

The state object contains only one property gameState which shows the game status (either nothing, someone wins, or draw). Given gameState can only have certain known string literal values, let's use string literal type and define the interface as follow before the class declaration.

interface GameStateBarState {
    gameState: "" | "X Wins!" | "O Wins!" | "Draw";
}

With the defined interface, change the GameStateBar class declaration,

export class GameStateBar extends React.Component<{}, GameStateBarState> {...}

Now, supply type information for its members. Note that providing types to all declarations is not required, but recommended for better type coverage.

// add types for params
constructor(props: {}) {...}
handleGameStateChange(e: CustomEvent) {...}
handleRestart(e: Event) {...}

// add types in arrow functions
componentDidMount() {
    window.addEventListener("gameStateChange", (e: CustomEvent) => this.handleGameStateChange(e));
    window.addEventListener("restart", (e: CustomEvent) => this.handleRestart(e));
}

// add types in arrow functions
componentWillUnmount() {
    window.removeEventListener("gameStateChange", (e: CustomEvent) => this.handleGameStateChange(e));
    window.removeEventListener("restart", (e: CustomEvent) => this.handleRestart(e));
}

To use stricter type checking, you can also specify useful compiler options in tsconfig.json. For example, noImplicitAny is a recommended option that triggers the compiler to error on expressions and declarations with an implied any type.

You can also add private/protected modifier to class members for access control. Let's mark handleGameStateChange and handleRestart as private as they are internal to gameStateBar.

private handleGameStateChange(e: CustomEvent) {...}
private handleRestart(e: Event) {...}

Again, try bundling the app with the following command and then open index.html in a browser,

npx webpack

Adopt TypeScript in the entire codebase

Adopting TypeScript in the entire codebase is more or less repeating the previous two steps for all js(x) files. You may need to make changes additional to what is mentioned above while converting perfectly valid JavaScript to TypeScript. However the TypeScript compiler and your editor (if it has TypeScript support) should give you useful tips and error messages. For instance, parameters can be optional in JavaScript, but in TypeScript all optional parameter must be marked with ?

You can see the fully converted TicTacToe project in the TicTacToe_TS folder. Build the app with,

npm install
npx webpack

Run the app by opening index.html.