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.
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 nulland 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 syntaxTuple Types
Tuples have a fixed number of elements with specific types.
let tuple: [number, boolean] = [0, false];any Type
anydisables 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; // error5.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 -D6.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.ts6.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
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
