From Skeptic to Fan: How TypeScript Won Me Over

This comprehensive guide explains why TypeScript has surpassed JavaScript in popularity, introduces its core concepts, basic and advanced types, generics, interfaces, classes, and modules, and provides step‑by‑step instructions for integrating TypeScript into both frontend and Node.js projects.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
From Skeptic to Fan: How TypeScript Won Me Over

1. Introduction

According to the 2018 Stack Overflow Developer Survey, TypeScript has become more popular than JavaScript among developers.

Initially I was not fond of TypeScript because I thought it required a lot of type declarations and limited the freedom of JavaScript, but after using it in a project I changed my mind.

2. What is TypeScript?

TypeScript, as the name suggests, adds type checking to JavaScript. It is a superset of JavaScript, fully compatible with plain JS syntax, but TypeScript code must be compiled before it can run in browsers or Node.

3. Why Use TypeScript?

Many developers avoid TypeScript because they value JavaScript's dynamic nature, yet dynamic code brings three main problems:

Poor readability and high maintenance cost. Without type declarations, understanding unfamiliar code requires mental guessing, especially in large projects without comments. TypeScript makes variable types and structures explicit, eliminating the need for guesswork.

Lack of type checking leads to frequent low‑level errors. Without static checks, assigning a number to a string variable or missing function parameters can cause bugs that waste debugging time. TypeScript highlights such mistakes instantly in the editor.

Uncertain types cause runtime type inference overhead. JavaScript parses and executes code on the fly, which can be less efficient when types are unknown. Although TypeScript itself does not solve this performance issue, tools like AssemblyScript can compile TypeScript to WebAssembly.

4. TypeScript Basics

4.1 Basic Types

Basic types include number, string, boolean, object, null, undefined, and symbol.

let num: number = 1; // declare a number variable
let str: string = 'string'; // declare a string variable
let bool: boolean = true; // declare a boolean variable
let obj: object = {
  a: 1,
}
let syb: symbol = Symbol(); // declare a symbol variable
null

and undefined can be assigned to any type except never.

Array Types

Two ways to declare arrays:

let arr: Array<number> = [1, 2, 3]; // using generic syntax
let arr: number[] = [1, 2, 3]; // using shorthand syntax

Tuple Types

Tuples have a fixed number of elements with specific types.

let tuple: [number, boolean] = [0, false];

any Type

any

disables type checking, allowing any property access or assignment.

let foo: any;
foo.test();
foo = 1;
foo = 'a';

void Type

Used for functions that do not return a value.

function foo(): void {
}

never Type

Indicates a function never returns normally (e.g., throws or infinite loop).

function error(message: string): never {
  throw new Error(message);
}
function infiniteLoop(): never {
  while (true) {}
}

enum Types

Enums assign friendly names to numeric or string values.

enum Color {Red, Green, Blue}
let c: Color = Color.Green;
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;
enum Color {Red = 'Red', Green = 'Green', Blue = 'Blue'}
let c: Color = Color.Green;

4.2 Type Assertions

Similar to casting in other languages; two syntaxes are available.

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

5. Advanced Topics

5.1 Functions

Function types declare parameter and return types.

function sum(a: number, b: number): number {
  return a + b;
}

Optional parameters are marked with ?:

function sum(a: number, b: number, c?: number): number {
  return c ? a + b + c : a + b;
}

Function overloads allow multiple signatures.

function doNothing(input: number): number;
function doNothing(input: string): string;
function doNothing(input: any): any {
  return input;
}

5.2 Interfaces

Interfaces describe object shapes and can also describe function types.

interface SquareConfig {
  color: string;
  width: number;
}
const square: SquareConfig = {color: 'red', width: 0};

Optional properties use ?, and readonly makes properties immutable.

interface Point {
  readonly x: number;
  readonly y: number;
}
let p: Point = {x: 10, y: 20};
// p.x = 20; // error

5.3 Classes

TypeScript classes extend JavaScript classes with additional modifiers.

readonly properties

public, private, protected modifiers

abstract classes

implementing interfaces

class User {
  readonly name: string;
  constructor(theName: string) {
    this.name = theName;
  }
}
let user = new User('Handsome');
// user.name = 'Handsomechan'; // error
class Animal {
  constructor(public name: string) {}
}
const animal = new Animal('tom');
console.log(animal.name);
class Animal {
  private name: string;
  constructor(name: string) { this.name = name; }
  getName(): string { return this.name; }
}
const animal = new Animal('tom');
console.log(animal.getName());
// console.log(animal.name); // error
class Animal {
  constructor(public name: string, protected age: number) {}
}
class Cat extends Animal {
  getAge = (): number => { return this.age; }
}
const cat = new Cat('tom', 1);
console.log(cat.getAge());
abstract class Animal {
  abstract makeSound(): void;
  move(): void { console.log('roaming the earth...'); }
}
class Sheep extends Animal {
  makeSound() { console.log('mie~'); }
}
const sheep = new Sheep();
sheep.makeSound();
sheep.move();
interface ClockInterface {
  currentTime: Date;
}
class Clock implements ClockInterface {
  currentTime: Date;
  constructor(h: number, m: number) {}
}

5.4 Generics

Generics allow writing reusable components with type parameters.

async function request<T>(url: string): Promise<T> {
  try {
    const result = await fetch(url).then(r => r.json());
    return result;
  } catch (e) {
    console.log('request fail:', e);
    throw e;
  }
}
function getLen<T extends Array<any> | string>(arg: T): number {
  return arg ? arg.length : 0;
}
function someFunction<T>(arg: T): T { return arg; }
console.log(someFunction<number>(123));
interface UserInfo<T> { id: T; age: number; }
const userInfo: UserInfo<number> = { id: 123, age: 23 };
type UserInfo<T> = { id: T; age: number; };
const userInfo2: UserInfo<string> = { id: '123', age: 123 };
class UserInfo<T> {
  constructor(private id: T, private age: number) {}
  getId(): T { return this.id; }
}
function logLength<T extends { length: number }>(arg: T): T {
  console.log(arg.length);
  return arg;
}

5.5 Advanced Types

Intersection types combine multiple types, while union types represent a value that can be one of several types.

interface typeA { a?: number; }
interface typeB { b?: number; }
let value: typeA & typeB = {};
value.a = 1; value.b = 2;
interface TypeA { a?: number; }
interface TypeB { b?: number; }
const value2: TypeA | TypeB = {};
(<TypeA>value2).a = 1;

5.6 Type Aliases

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;

5.7 Type Guards (is)

function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}
if (isFish(pet)) {
  pet.swim();
} else {
  pet.fly();
}

5.8 keyof

interface Person { name: string; age: number; }
type IndexType = keyof Person; // 'name' | 'age'
function pick<T, K extends keyof T>(obj: T, keys: K[]): T[K][] {
  return keys.map(key => obj[key]);
}

5.9 Declaration Merging

Interfaces, namespaces, classes, and functions can be merged to extend existing types.

interface Box { height: number; width: number; }
interface Box { scale: number; }
let box: Box = {height: 5, width: 6, scale: 10};
namespace Animals { export class Zebra {} }
namespace Animals { export interface Legged { numberOfLegs: number; } export class Dog {} }
class Album { label: Album.AlbumLabel; }
namespace Album { export class AlbumLabel {} }
function buildLabel(name: string): string {
  return buildLabel.prefix + name + buildLabel.suffix;
}
namespace buildLabel { export let suffix = ""; export let prefix = "Hello, "; }

5.10 Declaration Files

Declaration files (.d.ts) describe the shape of JavaScript libraries for TypeScript.

declare var jQuery: (selector: string) => any;
declare function jQuery(selector: string): any;
declare class Animal { name: string; constructor(name: string); sayHi(): string; }
declare enum Directions { Up, Down, Left, Right }

6. Project Integration

6.1 Installing TypeScript

npm i typescript -D

6.2 tsconfig.json

{
  "compilerOptions": {
    "noImplicitAny": false,
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "sourceMap": true,
    "outDir": "./out",
    "module": "commonjs",
    "baseUrl": "./src"
  },
  "include": ["./src/**/*"],
  "exclude": ["./out"]
}

6.3 Frontend (Webpack)

npm i ts-loader -D
module.exports = {
  mode: "development",
  devtool: "inline-source-map",
  entry: "./app.ts",
  output: { filename: "bundle.js" },
  resolve: { extensions: [".ts", ".tsx", ".js", ".jsx"] },
  module: { rules: [{ test: /\.tsx?$/, loader: "ts-loader" }] }
};

6.4 Node (ts-node)

npm i ts-node -D
npx ts-node script.ts

6.5 ESLint for TypeScript

npm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -D
module.exports = {
  parser: '@typescript-eslint/parser',
  extends: ['eslint-config-imweb', 'plugin:@typescript-eslint/recommended'],
  plugins: ['@typescript-eslint'],
  rules: {
    'react/sort-comp': 0,
    'import/extensions': 0,
    'import/order': 0,
    'import/prefer-default-export': 0,
    'react/no-array-index-key': 1,
  },
};

Configure VS Code to lint TypeScript files by adding the following to settings.json:

"eslint.validate": [
  "javascript",
  "javascriptreact",
  { "language": "typescriptreact", "autoFix": true },
  { "language": "typescript", "autoFix": true }
]

6.6 Migrating JavaScript Projects

For large existing codebases, enable allowJs in tsconfig.json to compile .js files alongside .ts files. Gradually convert files to TypeScript, add .d.ts declaration files for shared utilities, or write custom type definitions for third‑party libraries.

References

TypeScript Chinese documentation: https://www.tslang.cn/docs/home.html

TypeScript tutorial: https://ts.xcatliu.com/

ESLint + Prettier for React + TypeScript: https://zhuanlan.zhihu.com/p/62401626

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

TypeScriptJavaScriptprogrammingGenericsTutorialInterfaces
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

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.