TypeScript 入门与进阶指南

223 阅读4分钟

TypeScript入门与进阶指南


一、环境与基础

1. 环境搭建

# 安装编译器
npm install -g typescript

# 初始化项目(生成 tsconfig.json)
tsc --init

# 实时编译(监听模式)
tsc -w

扩展说明

  • 使用 tsc --init 生成的 tsconfig.json 是 TypeScript 项目的核心配置文件,支持自定义编译规则。
  • 若需支持现代浏览器,可设置 "target": "ES6",若需要兼容旧环境,可降级到 "ES5"
  • 推荐结合 nodemon 实现开发热重载:
    npm install --save-dev nodemon
    # 在 package.json 中添加脚本:
    "scripts": {
      "dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"
    }
    

2. 核心类型系统

基础类型注解
// 基本类型
let age: number = 25;             
const isAdmin: boolean = true;    
let data: any = fetchData();      // 慎用 any,建议用 unknown

// 枚举类型(双向映射)
enum Status {
  Pending = "pending",
  Success = "success",
  Error = "error",
}
const currentStatus: Status = Status.Success;

// 联合类型与字面量类型
type Result = "success" | "error" | 404;
const response: Result = "success";
复合类型
// 数组类型(两种写法)
let nums: number[] = [1, 2, 3];
let users: Array<{ id: number }> = [{ id: 1 }];

// 元组类型(固定长度与类型)
let point: [number, number] = [10, 20];
let httpStatus: [number, string] = [200, "OK"];

// 对象类型(内联注解)
const user: { 
  id: number; 
  name: string 
} = { id: 1, name: "Alice" };
接口与类型别名
// 接口(支持继承)
interface User {
  id: number;
  readonly username: string;  // 只读属性
  email?: string;             // 可选属性
}

interface Admin extends User {
  permissions: string[];
}

// 类型别名(联合/交叉类型)
type ID = number | string;
type AdminProfile = User & { 
  role: "admin"; 
  loginTime: Date 
};

二、类型系统进阶

1. 泛型编程

// 泛型函数(多场景应用)
function identity<T>(arg: T): T {
  return arg;
}

// 泛型接口(可复用类型定义)
interface ApiResponse<T> {
  code: number;
  data: T;
  message?: string;
}

// 泛型类(类级别类型约束)
class Queue<T> {
  private data: T[] = [];
  push(item: T) { this.data.push(item); }
  pop(): T | undefined { return this.data.shift(); }
}

// 内置工具类型示例
type UserKeys = keyof User; // "id" | "username" | "email"
type PartialUser = Partial<User>; // 所有属性变为可选

2. 高级类型工具

// 条件类型(类型分发)
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<42>;      // false

// 映射类型(动态生成类型)
type ReadonlyUser = {
  readonly [K in keyof User]: User[K];
};

// 实用类型扩展
type AsyncReturnType<T> = T extends (...args: any[]) => Promise<infer R> 
  ? R 
  : never;

// 示例:获取异步函数返回值类型
async function fetchUser(): Promise<User> { /* ... */ }
type UserResponse = AsyncReturnType<typeof fetchUser>; // User

3. 类型守卫与类型收窄

// 类型守卫(联合类型区分)
function isString(value: unknown): value is string {
  return typeof value === "string";
}

// 类型收窄示例
function processValue(value: string | number) {
  if (isString(value)) {
    console.log(value.toUpperCase()); // 此处 value 为 string
  } else {
    console.log(value.toFixed(2));    // 此处 value 为 number
  }
}

// 使用 in 操作符守卫
interface Cat { meow(): void }
interface Dog { bark(): void }
function act(animal: Cat | Dog) {
  if ("meow" in animal) {
    animal.meow();
  } else {
    animal.bark();
  }
}

三、工程化实践

1. tsconfig 深度解析

{
  "compilerOptions": {
    "target": "ES2022",       // 编译目标版本
    "module": "ESNext",       // 模块系统规范
    "strict": true,           // 启用所有严格检查
    "noImplicitAny": true,     // 禁止隐式 any
    "moduleResolution": "NodeNext", // 模块解析策略
    "baseUrl": "./",          // 基础路径
    "paths": {                // 路径别名
      "@utils/*": ["src/utils/*"]
    },
    "outDir": "./dist",       // 输出目录
    "rootDir": "./src"        // 源码目录
  }
}

配置建议

  • 大型项目可使用 "composite": true"references" 实现项目引用。
  • 启用 "strictNullChecks": true 避免空值错误。

2. 构建工具集成详解

Webpack 配置示例
// webpack.config.js
module.exports = {
  entry: "./src/index.ts",
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: [".ts", ".js"],
  },
};
Vite 集成优化
# 创建 Vite + TS 项目
npm create vite@latest my-app -- --template react-ts
  • Vite 内置对 TypeScript 的支持,无需额外配置。
  • 若需自定义类型检查规则,可扩展 vite.config.ts

四、框架集成

1. React 类型化高阶组件

// 带默认属性的组件
interface ButtonProps {
  size?: "small" | "medium" | "large";
  onClick: () => void;
}

const Button: React.FC<ButtonProps> = ({ 
  size = "medium", 
  onClick, 
  children 
}) => (
  <button className={`btn-${size}`} onClick={onClick}>
    {children}
  </button>
);

// 泛型组件示例
interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
}

function List<T>({ items, renderItem }: ListProps<T>) {
  return <div>{items.map(renderItem)}</div>;
}

2. Vue 3 类型强化

<script setup lang="ts">
import { ref, computed } from 'vue'

// 类型化响应式数据
interface Product {
  id: number;
  name: string;
  price: number;
}

const products = ref<Product[]>([]);
const totalPrice = computed(() => 
  products.value.reduce((sum, p) => sum + p.price, 0)
);

// 类型化 Emit
const emit = defineEmits<{
  (e: 'update', product: Product): void
}>();
</script>

3. Node.js 类型化中间件

import express, { RequestHandler } from 'express';

// 自定义请求上下文类型
interface AuthRequest extends express.Request {
  user?: { id: string; role: string };
}

// 类型化中间件
const authMiddleware: RequestHandler = (req: AuthRequest, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (token) {
    req.user = { id: "1", role: "admin" }; // 模拟解码
    next();
  } else {
    res.status(401).send("Unauthorized");
  }
};

五、最佳实践

1. 类型安全进阶策略

  • 从 any 到 unknown
    function safeParse(json: string): unknown {
      return JSON.parse(json);
    }
    const data = safeParse('{"id":1}') as { id: number }; // 显式断言
    
  • 防御性类型检查
    function isUser(obj: unknown): obj is User {
      return typeof obj === "object" && obj !== null && "id" in obj;
    }
    

2. 模块化工程规范

src/
  types/           // 全局类型声明(*.d.ts)
  utils/           // 工具函数(类型化导出)
    formatter.ts
    validator.ts
  features/        // 功能模块
    user/
      types.ts     // 模块专属类型
      api.ts
      components/
  services/        // API 服务层(类型化请求)
    apiClient.ts

六、调试与优化

1. 高级调试技巧

// .vscode/launch.json
{
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Current Test",
      "runtimeArgs": [
        "--inspect-brk",
        "-r",
        "ts-node/register"
      ],
      "args": ["${relativeFile}"]
    }
  ]
}
  • 使用 debugger 关键字在代码中设置断点。
  • 条件断点:在 VS Code 编辑器的断点侧边栏右键设置条件。

2. 编译性能优化

// tsconfig.json
{
  "compilerOptions": {
    "incremental": true,    // 增量编译
    "tsBuildInfoFile": "./.tsbuildinfo" // 缓存文件路径
  }
}
  • 大型项目使用 "composite": true 和项目引用拆分代码库。
  • 定期运行 tsc --build --clean 清理构建缓存。

附录:资源推荐

学习路径

  1. 官方文档TypeScript Handbook

工具生态扩展

工具库用途示例场景
Zod运行时类型校验表单数据验证
TypeGraphQLGraphQL 类型生成构建类型安全的 GraphQL API
ts-toolbelt高级类型工具库复杂类型操作