TypeScript完全指南:写出更好的JavaScript代码

了解 TypeScript 是什么

背景

TypeScript 是由 Microsoft 开发和维护的一个开源编程语言。它是 JavaScript 的一个超集,意味着任何有效的 JavaScript 代码也是有效的 TypeScript 代码。TypeScript 在 JavaScript 的基础上增加了类型系统和对 ES6+ 新特性的支持,目的是帮助开发者在开发大型应用时提高代码的可靠性和开发效率。

优势
  • 类型系统:TypeScript 的最大优势是其静态类型系统,它可以在编译时捕获常见的错误,提高开发效率和代码质量。
  • ES6+ 支持:TypeScript 支持最新的 JavaScript 特性,包括但不限于类、模块、箭头函数等。
  • 工具支持:得益于类型系统,TypeScript 在代码编辑器和 IDE 中提供了更好的自动完成、导航和重构功能。
  • 社区与生态:TypeScript 有着强大的社区支持和丰富的类型定义库(DefinitelyTyped),使得在 TypeScript 中使用第三方 JavaScript 库变得简单。
如何在 JavaScript 的基础上添加了类型系统

TypeScript 通过为变量、函数参数和返回值等添加类型注解,引入了静态类型检查。这些类型注解是可选的,使得开发者可以逐渐迁移到 TypeScript 上。

安装和配置

安装 TypeScript 编译器

可以通过 npm(Node.js 的包管理器)安装 TypeScript 编译器:

npm install -g typescript

这条命令会全局安装 TypeScript 编译器,让我们能在任何地方通过命令行使用 tsc 命令。

配置 tsconfig.json 文件

tsconfig.json 文件用于指定编译器如何编译 TypeScript 代码。创建此文件可以通过运行 tsc --init 命令。在这个文件中,可以配置诸如编译目标版本、模块系统、源映射支持等选项。

基本类型

TypeScript 支持 JavaScript 的所有基本类型,同时引入了一些新的类型,以帮助开发者更精确地描述变量的类型:

  • string:文本数据类型,如 "hello, TypeScript"
  • number:数字类型,包括整数和浮点数,如 423.14
  • boolean:布尔值类型,truefalse
  • array:数组类型,可以是 number[]Array<number>
  • tuple:元组类型,允许表示一个已知元素数量和类型的数组,每个元素的类型不必相同,如 [string, number]
  • enum:枚举类型,用于定义一组命名常量。
  • any:任意类型,可以是任何类型的值。尽量避免使用,以充分利用 TypeScript 的类型系统。
  • void:表示没有任何类型,常用于没有返回值的函数。
  • null 和 undefined:与 JavaScript 中的 nullundefined 值相对应。

变量声明

TypeScript 支持使用 letconst 进行变量声明,这两种声明方式都提供了块级作用域:

  • let:用于声明一个可变的变量。
  • const:用于声明一个常量,声明时必须初始化,且不能再被重新赋值。

在 TypeScript 中,建议尽量使用 const 来声明变量,除非确定变量的值会改变,这样做可以帮助避免编程中的一些错误。

类型系统深入

接口

在 TypeScript 中,接口(Interfaces)用于定义对象的形状,即指定对象应有哪些属性以及属性的类型。接口是定义代码约束和契约的强大方式,而不是为了实现它们。

interface Person {
  name: string;
  age: number;
}

function greet(person: Person) {
  console.log("Hello, " + person.name);
}

TypeScript 的类(Classes)语法是基于 ES6 的类语法,并添加了一些新的特性,如类型注解、接口实现、静态属性等。类可以实现接口,用于定义一个具有某些特定属性和方法的对象。

interface Person {
  name: string;
  greet(): void;
}

class Employee implements Person {
  constructor(public name: string, public position: string) {}

  greet() {
    console.log(`Hello, my name is ${this.name} and I work as a ${this.position}.`);
  }
}

类也支持继承,允许创建一个子类,继承父类的属性和方法,并添加新的或修改现有的属性和方法。

class Manager extends Employee {
  constructor(name: string, position: string, public department: string) {
    super(name, position);
  }

  greet() {
    console.log(`Hello, I'm ${this.name}, the manager of the ${this.department} department.`);
  }
}
函数

TypeScript 允许为函数的参数和返回值指定类型。此外,还可以定义可选参数、默认参数、剩余参数等。

function buildName(firstName: string, lastName?: string): string {
  if (lastName) return `${firstName} ${lastName}`;
  else return firstName;
}

function buildAddress(...streets: string[]): string {
  return streets.join(", ");
}
泛型

泛型(Generics)是 TypeScript 的一个重要特性,允许创建可在多个类型之间工作的组件。它们用于创建高度可重用的组件,能够支持任何类型。

function identity<T>(arg: T): T {
  return arg;
}

let output1 = identity<string>("myString");
let output2 = identity<number>(100);
TypeScript 的逻辑控制语法

TypeScript 的逻辑控制语法与 JavaScript 非常相似,因为 TypeScript 是 JavaScript 的超集。这包括条件语句、循环语句等。

  • 条件语句(如 ifelseswitch)用于基于不同条件执行不同的代码分支。
if (condition) {
  // do something when condition is true
} else {
  // do something when condition is false
}
  • 循环语句(如 forwhiledo...while)用于重复执行一段代码。
for (let i = 0; i < 5; i++) {
  console.log(i);
}

let i = 0;
while (i < 5) {
  console.log(i);
  i++;
}
  • for…of 循环用于遍历可迭代对象(如数组、字符串)的元素。
let array = [10, 20, 30];
for (let value of array) {
  console.log(value); // 10, 20, 30
}
  • for…in 循环用于遍历对象的键。
let obj = {a: 1, b: 2, c: 3};
for (let key in obj) {
  console.log(key); // 'a', 'b', 'c'
}

使用这些逻辑控制结构时,TypeScript 提供的类型系统可以帮助确保变量的类型安全,例如,在条件检查中使用类型守卫来细化类型。

高级主题

高级类型
  • 联合类型:允许一个值是几种类型之一,使用竖线(|)分隔每个类型。这对于函数参数或变量可以接受不同类型的值时非常有用。
function printId(id: number | string) {
  console.log("Your ID is: " + id);
}
  • 交叉类型:允许将多个类型合并为一个类型,使用 & 符号。这对于需要将多个类型的属性组合到一起的对象非常有用。
interface Name {
  name: string;
}

interface Age {
  age: number;
}

type Person = Name & Age;

let p: Person = { name: "Alice", age: 25 };
  • 类型守卫:是执行运行时检查的一种方式,可以确保在某个作用域内变量属于某个特定的类型。
function isNumber(x: any): x is number {
  return typeof x === "number";
}

function isString(x: any): x is string {
  return typeof x === "string";
}
  • 类型断言:允许手动指定一个值的类型,使用 as 关键字或尖括号语法。
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
装饰器

装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、访问符、属性或参数上。装饰器使用 @expression 形式,expression 求值后必须为一个函数,它会在运行时被调用。

function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealed
class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
  greet() {
    return "Hello, " + this.greeting;
  }
}
命名空间和模块
  • 命名空间:是 TypeScript 的一个早期方式,用于组织代码和避免全局作用域污染。虽然在使用模块的项目中不常用,但在某些情况下仍然有用。
namespace Validation {
  export interface StringValidator {
    isAcceptable(s: string): boolean;
  }
}
  • 模块:TypeScript 模块的概念与 ES6 模块相似,用于组织和封装代码。每个模块可以导出或导入类、接口、函数、对象等。
// someModule.ts
export function someFunction() { /*...*/ }

// otherModule.ts
import { someFunction } from "./someModule";
映射类型

映射类型允许从一个旧的类型生成一个新的类型,其中的属性是基于旧类型的属性进行转换的。

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

type Partial<T> = {
  [P in keyof T]?: T[P];
};

interface Person {
  name: string;
  age: number;
}

type ReadonlyPerson = Readonly<Person>;
type PartialPerson = Partial<Person>;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏目艾拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值