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!
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:
- 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.
- 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.
- Improved Code Readability: Typescript's type annotations can make your code easier to read and understand, especially for larger codebases.
- 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!