Published on

Quick Tips For Migrating from JavaScript to TypeScript

Authors
javascript-to-typescript

This blog post contains some tips I learned while migrating some JavaScript files to TypeScript of an open-source project.

A Brief Introduction To TypeScript

For those who may have never heard of TypeScript, It is a programming language originally developed and maintained by Microsoft that first appeared in October 2012. In terms of functionalities, TypeScript is just JavaScript plus some other features which include assigning static types to variables.

Some Notes on TypeScript

  • Because TypeScript is just a superset of JavaScript, every JavaScript code is a valid TypeScript code

  • TypeScript files usually have the extension .ts

  • TypeScript code is compiled to plain JavaScript code which is what browsers understand (Browsers don’t understand TypeScript).

The good news is, if you know JavaScript, you already know a lot about TypeScript.

Type System in TypeScript

The use of a type system in any programming language is to check the validity of the supplied values before they are stored or manipulated by the program. This prevents the program from having any unexpected behaviors and ensures that the code behaves as expected. In TypeScript, you can assign types to the declared variables in the following way :

let firstName: string = 'ismail';

You can see more details about TypeScript and types in TypeScript on their very good official documentation

Convert a JavaScript File to TypeScript

Before you start migrating, you must make sure to have certain configurations set up very early in your project. This includes setting up the tsconfig.json file and integrating TypeScript with all the tools you intend to use. You can check this page for further information.

TypeScript Configuration File

Here is a good explanation of the role of the TypeScript configuration file from the official documentation: "The presence of a tsconfig.json file in a directory indicates that the directory is the root of a TypeScript project. The tsconfig.json file specifies the root files and the compiler options required to compile the project." You can generate that file in your project with this simple command

tsc --init

You don’t have to use all the options present in the file generated. You can use only the options you need.

Here is a simple boilerplate configuration file that you can use to start off your project

{
  "include": ["./src/**"],
  "compilerOptions": {
    "target": "es2020",
    "module": "es2020",
    "moduleResolution": "node",
    "allowJs": true,
    "strict": true,
    "noEmit": true
  }
}

In this configuration file, you mainly tell the TypeScript compiler to take into account all the files in the src folder and to compile them in the ES2020 syntax.

Start Migrating Your JavaScript Files to TypeScript

Firstly, you don’t necessarily have to migrate all your JavaScript files. You can keep some in JavaScript format if you want.

The first step in migrating to TypeScript is to rename your JavaScript files from .js to .ts. If you are using JSX, you have to rename your file to .tsx. If you open your newly created file in some code editor supporting TypeScript, you might see some errors showing up. Your objective will be to get rid of those errors while still staying as close as possible to the TypeScript features.

First potential error : Cannot find a module

The first error you might encounter is some modules that might not be found in your import statements.

Cannot-find-module

This just means that the modules aren’t defined in the declaration file in your project. What you have to do is install those missing modules prefixed by @types. A package name prefixed by @types is, simply put, just a customized version of that package for TypeScript. As an example, if TypeScript does complain that React is missing, you can fix that easily by installing @types/react in the following way

npm install --save-dev @types/react

Dealing with Types

As we previously mentioned, one big advantage of using TypeScript is assigning types to variables. Doing so increases the readability of the program and makes it less prone to having bugs. Below are some remarks to keep in mind when you will be assigning types to variables.

  • Dealing with the “any” type : The any type is the supertype of all types in TypeScript. It refers to a dynamic type. Using the any type is equivalent to removing type checking for a variable. This should be used only as a last resort because you won’t be benefiting from type checking when using it.
  • Dealing with null or undefined : When some variable in your code can be null or undefined, you can explicitly tell TypeScript that it isn’t with the exclamation mark.
function computeGlobalGrade(studentName: string | undefined | null) {
  const nameOne: string = studentName;
  // Typescript will complain that the student name might be null and cannot be assigned to a string

  const nameTwo: string = studentName!;
  // compiles fine because you tell compiler that null | undefined are excluded
}
  • Typing a list of properties : If you have a list of properties like in a JavaScript Object, you can type them using either the type keyword or by creating an interface. Both are correct usages, but using interfaces provides the additional benefit usually used in Object-Oriented programming languages that they can be extended. As an example, if you are converting a React component from JSX to TSX, and there is a PropTypes list defined like in the following :
const propTypes = {
  i18nCertText: PropTypes.string,
  isProjectsCompleted: PropTypes.bool,
  steps: PropTypes.string,
  superBlock: PropTypes.string,
};

You can convert that using either an interface in your TypeScript file as shown below

interface ClaimCertStepsProps {
  i18nCertText: string;
  isProjectsCompleted: boolean;
  steps: string;
  superBlock: string;
}

or using the type keyword as shown below

type ClaimCertStepsProps = {
  i18nCertText: string;
  isProjectsCompleted: boolean;
  steps: string;
  superBlock: string;
};

and then use that in your component in the following way

const ClaimCertSteps = ({
  isProjectsCompleted,
  i18nCertText,
  steps,
  superBlock,
}: ClaimCertStepsProps): JSX.Element => {
  // code of the component
};

Adding a List of Properties To an Object

One typical block of code we find in JavaScript programs is dynamically adding properties to an object like so

let students = {};
students.name = 'ismail';
students.age = 15;

If you use the same code in TypeScript, the compiler will complain that the name and age properties does not exist on the students variable which has the type .

To get rid of that error, you can define the properties inside the object like so :

let student = {
  name: 'ismail',
  age: 15,
};

Or you can define the types of the properties in a separate interface like so :

interface SudentProperties {
  name?: string;
  age?: number;
}

let student: SudentProperties = {};

student.name = 'ismail';
student.age = 15;

Final words

Migrating a project to TypeScript is not that much of a hassle. As every JavaScript code is a valid TypeScript code, you can choose to only convert the files where you need strict typing and then go over the remaining files as you want.

The list above of tips is far from being exhaustive. There is a guide on the official TypeScript documentation that provides more information.