My experience migrating from JavaScript to Typescript and guide

My personal experience migrating from JavaScript to Typescript and a short guide highlighting why TypeScript might be an improvement for you and why you will be unlikely to look back!

Typescript
,

Unless you are brand new to Web or NodeJS development you will have heard of Typescript. I will admit I was dubious at first as a Frontend Developer I was quite happy defining my React props with prop-types and providing default props to prevent failures. In essence I was comfortable.

So when I was asked to start using Typescript it didn't feel like I was solving a problem I personally encountered. Worse, when I first started the team I was working in would make breaking changes to types held in our companies shared libraries causing build issues even though the code still worked. Very Frustrating!

However, the more I have used Typescript the more I see it's benefits.

Why Migrate to Typescript?

There are several benefits to migrating your codebase to Typescript:

  1. Type Safety: Typescript allows you to add type annotations to your code, which can help catch errors before they occur. This can make your code more reliable and easier to maintain.
  2. Better Tooling Support: Typescript has excellent tooling support, including code editors, linters, and debuggers. This can help improve your development experience and make it easier to write bug-free code.
  3. Improved Code Readability: Typescript's type annotations can make your code easier to read and understand, especially for larger codebases.
  4. Scalability: Typescript is designed for large-scale applications, making it easier to maintain and scale your codebase over time.

Migrating to Typescript

Migrating to Typescript can be a gradual process. You can start by adding type annotations to your existing JavaScript code, then gradually converting functions and classes to Typescript.

Setup

To get started with Typescript, you'll need to install it as a dev dependency:

npm install --save-dev typescript

You'll also need to create a tsconfig.json file in the root of your project. This file specifies the configuration for Typescript. Here's an example configuration for a React project.

{
  "compilerOptions": {
    "target": "es6",
    "module": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "jsx": "react-jsx",
    "strict": true,
    "esModuleInterop": true,
    "sourceMap": true,
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

and an example for a NodeJS project:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

You may create a tsconfig.json file for your development and build environments to exclude specific test files for example:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "moduleResolution": "node",
    "allowJs": true
  },
  "exclude": ["node_modules", "**/**.test**"]
}

In this example, the extends property is used to indicate that this configuration extends the existing tsconfig.json file. The compilerOptions section is overridden to include an outDir property that specifies the output directory for compiled files, a moduleResolution property that changes the module resolution strategy to node, and an allowJs property that allows the compiler to process .js files as well.

The exclude section is also extended to include files with .test in in the filename in addition to the node_modules directory.

By extending an existing tsconfig.json file, you can avoid repeating configuration options and keep your project's configuration organized and maintainable.

Understanding Typescript

Before you start migrating your codebase, it's important to understand the basics of Typescript.

Type Annotations

Type annotations are a core feature of Typescript. They allow you to specify the type of a variable or function parameter. For example:

function greet(name: string) {
  console.log(`Hello, ${name}!`)
}

In this example, the name parameter has a type of string.

Interfaces

Interfaces are another core feature of Typescript. They allow you to define a contract for an object, specifying the properties and their types. For example:

interface User {
  id: number
  name: string
  email: string
}

In this example, the User interface defines an object with three properties: id, name, and email.

Classes

Classes in Typescript work much like classes in JavaScript, but with the addition of type annotations and interfaces. For example:

interface Animal {
  name: string
  eat(food: string): void
}

class Dog implements Animal {
  name: string

  constructor(name: string) {
    this.name = name
  }

  eat(food: string) {
    console.log(`${this.name} is eating ${food}`)
  }
}

In this example, the Dog class implements the Animal interface, defining the name property and eat method.

Functions

/*
* In this example, the `addNumbers` function takes two parameters of type `number`
* and returns a value of type `number`.
*/ 
function addNumbers(a: number, b: number): number { 
  return a + b
}

In functions the return type is defined by writing** : <type>** after the parenthesis

You can also add type annotations to variables but Typescript is also smart enough to guess the type for you.

const name: string = "John";

Conclusion

Migrating from JavaScript to Typescript can be a gradual process, but it's worth the effort. Typescript can make your code more reliable, easier to maintain, and more scalable. With this guide, you have the basic knowledge and understanding to start migrating your codebase to Typescript.

For new projects I would highly recommend jumping in and giving it a try as you will have type safety and readability from the very beginning so far less will go wrong!

© ARCHILTON LTD 2023