LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

TypeScript对比JavaScript,有哪些核心区别和优势

admin
2025年3月31日 16:54 本文热度 201

JavaScript对比TypeScript

作为一名 JavaScript 工程师,我经常被问到:"为什么要使用 TypeScript?"或者"TypeScript 相比 JavaScript 有什么优势?"今天,让我们通过实际的代码示例来深入探讨这个话题。

核心特性对比

1. 类型系统:最显著的区别

​javascript

// JavaScript function calculateTotal(items) { return items.reduce((total, item) => total + item.price, 0); } // 这段代码可能在运行时出错 const items = [ { price: 10 }, { price: 20 }, { notPrice: 30 } // 这里会导致运行时错误 ]; console.log(calculateTotal(items)); // 运行时才发现 undefined + number 的错误

typescript

// TypeScript interface Item { price: number; } function calculateTotal(items: Item[]): number { return items.reduce((total, item) => total + item.price, 0); } // 在编译时就会发现错误 const items = [ { price: 10 }, { price: 20 }, { notPrice: 30 } // TypeScript 会在编译时报错! ];

2. 接口和类型定义

javascript

// JavaScript const user = { name: 'John', age: 30, address: { street: '123 Main St', city: 'Boston' } }; // 没有明确的契约,可能导致使用时的不确定性 function updateUser(user) { // 这里我们并不确定 user 对象应该包含哪些属性 user.name = 'Jane'; }

typescript

// TypeScript interface Address { street: string; city: string; zipCode?: string; // 可选属性 } interface User { name: string; age: number; address: Address; } function updateUser(user: User): void { user.name = 'Jane'; // IDE 会提供完整的属性提示 }

3. 函数重载

javascript

// JavaScript function process(input) { if (typeof input === 'string') { return input.toUpperCase(); } else if (Array.isArray(input)) { return input.map(item => item.toUpperCase()); } throw new Error('Unsupported input type'); }

typescript

// TypeScript function process(input: string): string; function process(input: string[]): string[]; function process(input: string | string[]): string | string[] { if (typeof input === 'string') { return input.toUpperCase(); } else { return input.map(item => item.toUpperCase()); } }

4. 泛型

javascript

// JavaScript function firstElement(arr) { return arr[0]; } // 无法在编译时确保类型安全 const numResult = firstElement([1, 2, 3]); const strResult = firstElement(['a', 'b', 'c']);

typescript

// TypeScript function firstElement<T>(arr: T[]): T | undefined { return arr[0]; } // 类型安全且具有更好的 IDE 支持 const numResult = firstElement([1, 2, 3]); // 类型为 number const strResult = firstElement(['a', 'b', 'c']); // 类型为 string

TypeScript 特有的语法特性

1. 类型注解(Type Annotations)

javascript

// JavaScript let name = "John"; let age = 30; let isStudent = true; let numbers = [1, 2, 3]; // JavaScript 中没有元组类型,使用普通数组 let tuple = ["hello", 10]; // JavaScript 中可以使用 JSDoc 注释来提供类型信息 /** * @param {string} name * @returns {string} */ function greet(name) { return `Hello, ${name}!`; }

typescript

// TypeScript let name: string = "John"; let age: number = 30; let isStudent: boolean = true; let numbers: number[] = [1, 2, 3]; let tuple: [string, number] = ["hello", 10]; // 函数参数和返回值的类型注解 function greet(name: string): string { return `Hello, ${name}!`; }

2. 枚举(Enums)

javascript

// JavaScript 实现方式 1:使用对象 const Direction = { Up: "UP", Down: "DOWN", Left: "LEFT", Right: "RIGHT", // 防止枚举值被修改 Object.freeze(Direction); }; // JavaScript 实现方式 2:使用 Symbol const Direction = { Up: Symbol("UP"), Down: Symbol("DOWN"), Left: Symbol("LEFT"), Right: Symbol("RIGHT") }; let playerDirection = Direction.Up; // 数字枚举的实现 const StatusCode = { OK: 200, NotFound: 404, Error: 500, Object.freeze(StatusCode); };

typescript

// TypeScript enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" } let playerDirection: Direction = Direction.Up; // 数字枚举 enum StatusCode { OK = 200, NotFound = 404, Error = 500 }

3. 类型断言(Type Assertions)

javascript

// JavaScript let someValue = "this is a string"; let strLength = someValue.length; // JavaScript 中使用类型检查 if (typeof someValue === 'string') { let strLength = someValue.length; } // DOM 操作 const myCanvas = document.getElementById('main_canvas'); if (myCanvas instanceof HTMLCanvasElement) { // 使用 canvas API const ctx = myCanvas.getContext('2d'); }

typescript

// TypeScript let someValue: any = "this is a string"; let strLength: number = (someValue as string).length; // 或者 let strLength: number = (<string>someValue).length; // DOM 操作的类型断言 const myCanvas = document.getElementById('main_canvas') as HTMLCanvasElement;

4. 访问修饰符

javascript

// JavaScript class Employee { #name; // 私有字段(ES2019+) _age; // 约定俗成的protected字段 department; constructor(name, age, department, id) { this.#name = name; this._age = age; this.department = department; Object.defineProperty(this, 'id', { value: id, writable: false // 实现 readonly }); } #getDetails() { // 私有方法(ES2019+) return `${this.#name} (${this._age})`; } }

typescript

// TypeScript class Employee { private name: string; protected age: number; public department: string; readonly id: number; constructor(name: string, age: number, department: string, id: number) { this.name = name; this.age = age; this.department = department; this.id = id; } private getDetails(): string { return `${this.name} (${this.age})`; } }

5. 抽象类和接口

javascript

// JavaScript // 模拟抽象类 class Animal { constructor() { if (new.target === Animal) { throw new Error('Animal is abstract'); } } makeSound() { throw new Error('makeSound must be implemented'); } move() { console.log("Moving..."); } } // 模拟接口 class Pet { constructor() { if (this.play === undefined) { throw new Error('Must implement play method'); } if (!this.name) { throw new Error('Must have name property'); } } } class Dog extends Animal { constructor(name) { super(); this.name = name; } makeSound() { console.log("Woof!"); } play() { console.log("Playing fetch!"); } }

typescript

// TypeScript abstract class Animal { abstract makeSound(): void; move(): void { console.log("Moving..."); } } interface Pet { name: string; play(): void; } class Dog extends Animal implements Pet { name: string; constructor(name: string) { super(); this.name = name; } makeSound(): void { console.log("Woof!"); } play(): void { console.log("Playing fetch!"); } }

6. 联合类型和交叉类型

javascript

// JavaScript function processValue(value) { if (typeof value === "string") { return value.toUpperCase(); } if (typeof value === "number") { return value * 2; } throw new Error('Invalid type'); } // 对象合并 const person = { ...{ name: "John" }, ...{ age: 30 } };

typescript

// TypeScript type StringOrNumber = string | number; type NameAndAge = { name: string } & { age: number }; function processValue(value: StringOrNumber) { if (typeof value === "string") { return value.toUpperCase(); } return value * 2; } const person: NameAndAge = { name: "John", age: 30 };

7. 可选链和空值合并

javascript

// JavaScript ES2020+ const user = { name: "John" }; // 可选链 const city = user.address?.city; // 空值合并 const street = user.address?.street ?? "Default Street"; // 旧版 JavaScript const city = user && user.address && user.address.city; const street = (user && user.address && user.address.street) || "Default Street";

typescript

// TypeScript(也适用于现代 JavaScript) interface User { name: string; address?: { street?: string; city?: string; }; } const user: User = { name: "John" }; // 可选链 const city = user.address?.city; // 空值合并 const street = user.address?.street ?? "Default Street";

8. 字面量类型

javascript

// JavaScript const CARDINAL_DIRECTIONS = ["North", "South", "East", "West"]; const DICE_VALUES = [1, 2, 3, 4, 5, 6]; function move(direction) { if (!CARDINAL_DIRECTIONS.includes(direction)) { throw new Error('Invalid direction'); } console.log(`Moving ${direction}`); } move("North"); // 有效 move("Northeast"); // 运行时错误

typescript

// TypeScript type CardinalDirection = "North" | "South" | "East" | "West"; type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6; function move(direction: CardinalDirection) { console.log(`Moving ${direction}`); } move("North"); // 有效 // move("Northeast"); // 编译错误

9. 类型别名和映射类型

javascript

// JavaScript const createPoint = (x, y) => ({ x, y }); // 创建只读对象 const createReadonlyPoint = (x, y) => Object.freeze({ x, y }); const point = createReadonlyPoint(10, 20); // point.x = 30; // 错误:Cannot assign to read only property 'x'

typescript

// TypeScript type Point = { x: number; y: number; }; type Readonly<T> = { readonly [P in keyof T]: T[P]; }; type ReadonlyPoint = Readonly<Point>; const point: ReadonlyPoint = { x: 10, y: 20 }; // point.x = 30; // 错误:无法分配到 "x" ,因为它是只读属性

10. 装饰器(Decorators)

javascript

// JavaScript(使用实验性的装饰器语法) function log(target, propertyKey) { console.log(`Accessing property: ${propertyKey}`); } class Example { @log name = "example"; } // JavaScript(不使用装饰器的替代方案) function makeLoggable(target) { const originalDescriptor = Object.getOwnPropertyDescriptor(target.prototype, 'name'); Object.defineProperty(target.prototype, 'name', { get() { console.log('Accessing property: name'); return originalDescriptor.get.call(this); }, set(value) { console.log('Setting property: name'); originalDescriptor.set.call(this, value); } }); return target; } @makeLoggable class Example { name = "example"; }

typescript

// TypeScript function log(target: any, propertyKey: string) { console.log(`Accessing property: ${propertyKey}`); } class Example { @log name: string = "example"; }

这些语法特性使得 TypeScript 能够:

  1. 提供更强大的类型检查和编译时验证
  2. 支持面向对象编程的高级特性
  3. 提供更好的代码组织和重用机制
  4. 增强代码的可读性和可维护性
  5. 提供更好的 IDE 支持和开发体验

虽然很多特性在现代 JavaScript 中也可以实现,但实现方式往往更复杂,且缺少编译时的类型检查。TypeScript 的优势在于它提供了更简洁、更安全的语法,以及强大的类型系统支持。

如何在项目中使用 TypeScript

1. 初始化项目

bash

# 创建新项目 mkdir my-ts-project cd my-ts-project npm init -y # 安装 TypeScript npm install typescript --save-dev # 初始化 TypeScript 配置 npx tsc --init

2. 配置 tsconfig.json

json

{ "compilerOptions": { "target": "es2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules"] }

3. 项目结构

css

my-ts-project/ ├── src/ │ └── index.ts ├── package.json ├── tsconfig.json └── node_modules/

4. 开发工作流

  1. 编写 TypeScript 代码(.ts 文件)
  2. 使用 tsc 编译代码:npx tsc
  3. 运行编译后的 JavaScript 代码:node dist/index.js

5. 推荐的开发工具

  • VS Code:内置 TypeScript 支持
  • ESLint 配置:

bash

npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint

总结

TypeScript 相比 JavaScript 的主要优势:

  1. 静态类型检查,提前发现潜在错误
  2. 更好的 IDE 支持,包括代码补全和重构
  3. 接口和类型定义提供更清晰的代码契约
  4. 更容易维护大型项目
  5. 通过类型推断减少文档需求

虽然需要一些学习成本,但 TypeScript 带来的好处远超过这些成本,特别是在大型项目中。作为一个 JavaScript 工程师,掌握 TypeScript 将显著提升你的开发效率和代码质量。


作者:AI编程产品人
链接:https://juejin.cn/post/7477104460452675594
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

该文章在 2025/4/1 13:16:43 编辑过
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved