TypeScript 教程

1. 核心知识点讲解

1.1 TypeScript 简介

TypeScript 是 JavaScript 的超集,添加了静态类型检查和其他特性,帮助开发者编写更可靠、更可维护的代码。它由 Microsoft 开发并维护,已成为前端和 Node.js 开发中的重要工具。

1.2 安装和配置

全局安装 TypeScript:

npm install -g typescript

项目本地安装:

npm install --save-dev typescript

创建 tsconfig.json 配置文件:

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

1.3 基本类型

TypeScript 提供了多种基本类型:

  • number: 数字类型
  • string: 字符串类型
  • boolean: 布尔类型
  • nullundefined
  • any: 任意类型
  • unknown: 未知类型
  • void: 无返回值
  • never: 永远不会返回
  • array: 数组类型
  • tuple: 元组类型

1.4 接口和类型别名

接口(Interface):

interface User {
  id: number;
  name: string;
  email?: string; // 可选属性
}

const user: User = {
  id: 1,
  name: "张三"
};

类型别名(Type Alias):

type UserId = number;
type User = {
  id: UserId;
  name: string;
  email?: string;
};

1.5 类和面向对象编程

类的定义:

class Person {
  private name: string;
  public age: number;
  protected address: string;

  constructor(name: string, age: number, address: string) {
    this.name = name;
    this.age = age;
    this.address = address;
  }

  getName(): string {
    return this.name;
  }
}

class Employee extends Person {
  private employeeId: string;

  constructor(name: string, age: number, address: string, employeeId: string) {
    super(name, age, address);
    this.employeeId = employeeId;
  }

  getEmployeeInfo(): string {
    return `${this.getName()}, ID: ${this.employeeId}`;
  }
}

1.6 泛型

泛型函数:

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

const output1 = identity<string>("hello");
const output2 = identity<number>(42);

泛型接口:

interface Container<T> {
  value: T;
  getValue(): T;
}

class NumberContainer implements Container<number> {
  value: number;
  constructor(value: number) {
    this.value = value;
  }
  getValue(): number {
    return this.value;
  }
}

1.7 模块和命名空间

ES 模块:

// math.ts
export function add(a: number, b: number): number {
  return a + b;
}

export function subtract(a: number, b: number): number {
  return a - b;
}

// app.ts
import { add, subtract } from './math';

console.log(add(1, 2)); // 3
console.log(subtract(5, 3)); // 2

1.8 编译和构建

编译 TypeScript 文件:

ts --build

使用 tsc 命令编译单个文件:

tsc app.ts

2. 实用案例分析

2.1 基本类型使用案例

场景: 定义用户信息对象,确保类型安全

实现:

interface User {
  id: number;
  name: string;
  email: string;
  age?: number;
  isActive: boolean;
}

function createUser(user: User): User {
  // 验证用户信息
  if (!user.name || !user.email) {
    throw new Error("用户名和邮箱是必填项");
  }
  
  return {
    ...user,
    id: user.id || Math.floor(Math.random() * 10000),
    isActive: user.isActive ?? true
  };
}

// 正确使用
const user1 = createUser({
  name: "张三",
  email: "zhangsan@example.com",
  age: 30,
  isActive: true
});

// 错误使用(缺少必填项)
// const user2 = createUser({
//   name: "李四"
//   // 缺少 email
// });

2.2 泛型工具类型案例

场景: 处理 API 响应数据,确保类型安全

实现:

// 定义 API 响应类型
interface ApiResponse<T> {
  success: boolean;
  data: T;
  error?: string;
}

// 定义用户类型
interface User {
  id: number;
  name: string;
  email: string;
}

// 定义产品类型
interface Product {
  id: number;
  name: string;
  price: number;
}

// 模拟 API 调用
function fetchData<T>(url: string): Promise<ApiResponse<T>> {
  return new Promise((resolve) => {
    // 模拟网络请求
    setTimeout(() => {
      resolve({
        success: true,
        data: {} as T
      });
    }, 1000);
  });
}

// 使用泛型获取用户数据
async function getUsers() {
  const response = await fetchData<User[]>("/api/users");
  if (response.success) {
    // response.data 类型为 User[]
    console.log(response.data);
  }
}

// 使用泛型获取产品数据
async function getProducts() {
  const response = await fetchData<Product[]>("/api/products");
  if (response.success) {
    // response.data 类型为 Product[]
    console.log(response.data);
  }
}

2.3 装饰器案例

场景: 实现一个简单的依赖注入系统

实现:

// 启用装饰器支持
// tsconfig.json 中添加:"experimentalDecorators": true

// 装饰器工厂
function Injectable() {
  return function (target: Function) {
    // 注册类到依赖注入容器
    console.log(`Registering ${target.name} to DI container`);
  };
}

// 服务类
@Injectable()
class UserService {
  getUser(id: number): { id: number; name: string } {
    return { id, name: `User ${id}` };
  }
}

// 控制器类
@Injectable()
class UserController {
  constructor(private userService: UserService) {}

  getUser(id: number) {
    return this.userService.getUser(id);
  }
}

// 使用
const userController = new UserController(new UserService());
console.log(userController.getUser(1)); // { id: 1, name: "User 1" }

3. 代码示例

3.1 完整的 TypeScript 项目结构

项目结构:

src/
├── index.ts
├── types/
│   └── index.ts
├── utils/
│   └── validation.ts
└── services/
    └── userService.ts

types/index.ts:

export interface User {
  id: number;
  name: string;
  email: string;
  age?: number;
}

export interface ApiResponse<T> {
  success: boolean;
  data: T;
  error?: string;
}

utils/validation.ts:

import { User } from '../types';

export function validateUser(user: Partial<User>): string[] {
  const errors: string[] = [];
  
  if (!user.name) {
    errors.push('用户名不能为空');
  }
  
  if (!user.email) {
    errors.push('邮箱不能为空');
  } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(user.email)) {
    errors.push('邮箱格式不正确');
  }
  
  if (user.age && (user.age < 0 || user.age > 150)) {
    errors.push('年龄必须在 0-150 之间');
  }
  
  return errors;
}

services/userService.ts:

import { User, ApiResponse } from '../types';
import { validateUser } from '../utils/validation';

class UserService {
  private users: User[] = [];
  private nextId = 1;

  createUser(userData: Partial<User>): ApiResponse<User> {
    const errors = validateUser(userData);
    
    if (errors.length > 0) {
      return {
        success: false,
        data: {} as User,
        error: errors.join(', ')
      };
    }

    const newUser: User = {
      id: this.nextId++,
      name: userData.name!,
      email: userData.email!,
      age: userData.age
    };

    this.users.push(newUser);

    return {
      success: true,
      data: newUser
    };
  }

  getUsers(): ApiResponse<User[]> {
    return {
      success: true,
      data: this.users
    };
  }

  getUserById(id: number): ApiResponse<User> {
    const user = this.users.find(u => u.id === id);
    
    if (!user) {
      return {
        success: false,
        data: {} as User,
        error: '用户不存在'
      };
    }

    return {
      success: true,
      data: user
    };
  }
}

export default new UserService();

index.ts:

import userService from './services/userService';

// 创建用户
const createResponse = userService.createUser({
  name: '张三',
  email: 'zhangsan@example.com',
  age: 30
});

console.log('创建用户响应:', createResponse);

// 获取所有用户
const getUsersResponse = userService.getUsers();
console.log('获取用户列表响应:', getUsersResponse);

// 根据 ID 获取用户
const getUserByIdResponse = userService.getUserById(1);
console.log('获取单个用户响应:', getUserByIdResponse);

// 错误案例:缺少必填项
const errorResponse = userService.createUser({
  name: '李四'
  // 缺少 email
});

console.log('错误响应:', errorResponse);

3.2 编译和运行

编译 TypeScript:

ts --build

运行编译后的 JavaScript:

node dist/index.js

4. 总结

TypeScript 是一种强大的编程语言,通过添加静态类型检查和其他特性,帮助开发者编写更可靠、更可维护的代码。本教程介绍了 TypeScript 的核心概念,包括:

  • 类型系统和基本类型
  • 接口和类型别名
  • 类和面向对象编程
  • 泛型和装饰器
  • 模块和命名空间
  • 编译和构建配置

通过学习这些概念,你可以开始在项目中使用 TypeScript,提高代码质量和开发效率。随着实践的深入,你会发现 TypeScript 带来的类型安全和开发体验的提升,特别是在大型项目中。

5. 进一步学习资源

希望本教程对你学习 TypeScript 有所帮助!

« 上一篇 76. Babel 教程 下一篇 » Jest 教程