Why You Should Switch to TypeScript: Benefits, Pitfalls, and Real‑World Examples

This article chronicles a developer's transition from plain JavaScript to TypeScript, illustrating how static typing improves code robustness, debugging, and documentation while also discussing migration steps, common pitfalls, and practical examples across frontend projects.

WecTeam
WecTeam
WecTeam
Why You Should Switch to TypeScript: Benefits, Pitfalls, and Real‑World Examples

Preface

According to the author, many developers avoid learning TypeScript because they think they don’t have time. Two months ago the author was one of them, but after seeing that a senior colleague used TypeScript with Vue 3, curiosity led to a deep dive and a revelation.

After understanding TypeScript for a while, the author wrote this article to provide a benefit analysis for those hesitating to learn or still observing TypeScript.

Recommendation

Is TypeScript hard to write? No. The simplest approach can be done in three steps.

1. Find a .js file

2. Rename it

3. Change the extension from .js to .ts

Done!

What is TypeScript

TypeScript is a superset of JavaScript, meaning any valid JavaScript syntax also works in TypeScript. It adds many constraints and extensions, similar to how ES6 introduced syntactic sugar. By following certain rules, you can enjoy the benefits TypeScript provides.

Because modern TypeScript is powerful and supported by VS Code, it empowers developers who previously avoided it.

The effort to convert JavaScript to TypeScript largely depends on how strictly you want to type your code. The simplest method is just renaming the file, though static checks may still fail. The more you type, the more your teammates will appreciate the code.

Below is a brief introduction to TypeScript syntax to aid later understanding.

TypeScript Syntax Overview

// 'xxx: number' declares a number type
const num: number = 123

// Declare a function with typed parameters (number and any) and a void return type
function fn(arg1: number, arg2: any): void {
    // todo
}

// Declare an interface
interface IPerson {
    name: string // IPerson requires a name property of type string
    age: number // IPerson requires an age property of type number
    family: Array<string> // family is an array of strings
    sex?: '男' | '女' // optional sex property
}

// Use the interface to type an object
const person: IPerson = {
    name: '小王',
    age: 12,
    family: ['爹', '娘']
}

// type is similar to interface; the following is equivalent
type IPerson2 = {
    name: string
    age: number
    family: Array<string>
    sex?: '男' | '女'
}

const person2: IPerson2 = person

Some readers might wonder why write so much extra code and increase file size. Generally, TypeScript needs to be compiled to JavaScript before running. The compiled output looks like this:

// 'xxx: number' declares a number type
var num = 123

// Declare a function with typed parameters (number and any) and a void return type
function fn(arg1, arg2) {
    // todo
}

fn(num, [1,2,3,4]);

// Use the interface to type an object (compiler will highlight errors if mismatched)
var person = {
    name: '小王',
    age: 12,
    family: ['爹','娘']
};

var person2 = person;

After a manual diff, you’ll see that the compiled code removes all TypeScript‑specific syntax.

Now, why learn TypeScript?

Application Scenarios

Here are several scenarios where TypeScript can be helpful.

Enforcing API contracts

In production code we often add many defensive checks for robustness. However, users may ignore documentation and pass wrong arguments, causing errors that the team must debug.

With TypeScript, incorrect arguments are flagged at edit time, providing friendly hints.

Define a function with typed parameters:

interface IArgs {
    name: string
    age: string
}

function youFoo(arg1: string, arg2: 'a'|'b', arg3: IArgs) {
    // nothing, just type checking
}

If a colleague calls it incorrectly:

youFoo('sss', 'c', { name: 'xiaoming', age: 18 })

TypeScript will highlight that the second argument must be 'a' or 'b' and that age should be a string.

Finding documentation

When working, developers often open a second screen to search APIs. With TypeScript, many errors are caught earlier, reducing the need to constantly look up documentation.

For example, a helper method can be written as:

/**
 * Generate an error message
 * @param {string} message - e.g. `you have an error`
 * @param {number|string} code - error code
 * @param {string} [type] - `demo1` or `demo2`
 */
export function genErrMsg(message: string, code: number|string, type?: 'demo1'|'demo2'): string {
    return (message || `网络繁忙,请稍候再试`) + (code ? `(${code})` : ``);
}

Using this function provides immediate feedback about argument types.

Identifying bugs in JavaScript

Given a JavaScript file with many similarly named variables, TypeScript can quickly surface undefined references.

let foooo = 1;
let fooo = 1;
let fooooooo = 1;
let foo = 1;
let foooooo = 1;
let test = 12;
const obj = {
    fn1(){},
    fn2(){},
    fn4(){},
};

// Below the line are bugs
obj.fn3(); // fn3 does not exist
console.leg(fooooo); // typo in console.log and variable name
function test(){
    alert(tast); // typo in variable name
}

TypeScript will highlight the missing method fn3, the typo leg, and the undefined identifiers.

Interface data uncertainty

When consuming an API whose response shape may change, TypeScript interfaces let you catch mismatches early.

interface IPriceData {
    /** Identifier */
    cbf: string;
    /** ID */
    id: string;
    /** Market price */
    m: string;
    /** Backend price */
    op: string;
    /** Frontend price */
    p: string;
}

type IPriceDataArray = Array<IPriceData>;

function getPrice() {
    return new Promise<IPriceDataArray>((resolve, reject) => {
        $.get('https://xxxxxxx/prices/pgets?ids=P_100012&area=&source=', data => {
            resolve(data);
        });
    });
}

When calling getPrice(), the IDE shows the exact shape of the resolved data, preventing silent errors.

Enhanced classes and enums

TypeScript augments JavaScript classes with access modifiers and static members, and provides enum syntax that allows reverse mapping.

enum HttpCode {
    /** Success */
    '200_OK' = 200,
    /** Created */
    '201_Created' = 201,
    /** Accepted */
    '202_Accepted' = 202,
    /** No Content */
    '204_NoContent' = 204,
    /** Multiple Choices */
    '300_MultipleChoices' = 300,
    /** Moved Permanently */
    '301_MovedPermanently' = 301,
    /** Move Temporarily */
    '302_MoveTemporarily' = 302,
}

// Reverse mapping example
HttpCode[HttpCode['200_OK']]; // yields '200_OK'
HttpCode[200]; // yields '200_OK'

Compiled JavaScript shows the bidirectional mapping.

"use strict";
var HttpCode;
(function (HttpCode) {
    /** Success */
    HttpCode[HttpCode["200_OK"] = 200] = "200_OK";
    /** Created */
    HttpCode[HttpCode["201_Created"] = 201] = "201_Created";
    /** Accepted */
    HttpCode[HttpCode["202_Accepted"] = 202] = "202_Accepted";
    /** No Content */
    HttpCode[HttpCode["204_NoContent"] = 204] = "204_NoContent";
    /** Multiple Choices */
    HttpCode[HttpCode["300_MultipleChoices"] = 300] = "300_MultipleChoices";
    /** Moved Permanently */
    HttpCode[HttpCode["301_MovedPermanently"] = 301] = "301_MovedPermanently";
    /** Move Temporarily */
    HttpCode[HttpCode["302_MoveTemporarily"] = 302] = "302_MoveTemporarily";
})(HttpCode || (HttpCode = {}));

Pros and Cons

Benefits observed from the examples include:

Clear function parameters and interface properties improve readability and maintainability.

Static checking catches errors early.

Automatic API documentation generation.

IDE assistance with suggestions.

Active community support.

Costs include:

Need to annotate types and declare interfaces/types.

Some libraries (e.g., Vue 2.x) have imperfect TypeScript integration.

When TypeScript Falls Short

Complex scenarios such as passing a generic options object to a library can still lack full type inference, requiring developers to either import the library’s types, move the options inline, or provide a helper wrapper.

TypeScript in JavaScript Projects

Even pure JavaScript files can benefit from TypeScript’s type checking if VS Code’s “Check JS” option is enabled.

Configuration files also gain autocomplete when a corresponding @types package is installed.

/**
 * webpack configuration autocomplete
 */
// @type {import('webpack').Configuration}
const config = {};

Conclusion

Even if you only know JavaScript, learning TypeScript is recommended because it deepens your understanding of the language and provides tooling that catches many bugs early. Resources for learning include the official TypeScript tutorial, Vue 3 TypeScript guides, concise articles, Stack Overflow, and general web searches.

References

[1]

TypeScript tutorial: https://github.com/xcatliu/typescript-tutorial/blob/master/README.md [2] TypeScript for Vue 3: https://juejin.im/entry/5d19adb3f265da1b7b31a28b [3] 30‑minute TypeScript overview: https://juejin.im/post/5d53a8895188257fad671cbc [4] Stack Overflow: https://stackoverflow.com/ [5] Google: https://www.google.com/

TypeScriptJavaScriptcode refactoringVueStatic Typing
WecTeam
Written by

WecTeam

WecTeam (维C团) is the front‑end technology team of JD.com’s Jingxi business unit, focusing on front‑end engineering, web performance optimization, mini‑program and app development, serverless, multi‑platform reuse, and visual building.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.