TypeScript 使用文档(基于 TypeScript 5.8.3)

本文档为 TypeScript 最新版(5.8.3)的使用指南,涵盖核心概念、类型系统、工具配置及高级特性,每项均附详细示例。TypeScript 是一种为 JavaScript 添加静态类型的超集,旨在提升代码健壮性和开发效率。以下内容适用于初学者和高级开发者。

1. 安装与配置

1.1 安装 TypeScript

TypeScript 可以通过 npm 安装,推荐在项目中局部安装以确保版本一致性。

# 全局安装
npm install -g typescript

# 项目局部安装
npm install --save-dev typescript

检查版本:

tsc --version

1.2 配置 tsconfig.json

tsconfig.json 是 TypeScript 的配置文件,控制编译行为。以下是一个推荐的配置示例:

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

示例:编译项目

tsc

运行 tsc 会根据 tsconfig.json 编译项目,生成 JavaScript 文件到 dist 目录。

2. 基本类型

TypeScript 的核心是静态类型系统,以下是常见基本类型及其用法。

2.1 基本类型(Primitive Types)

包括 stringnumberbooleannullundefined 等。

let name: string = "Alice";
let age: number = 25;
let isStudent: boolean = true;
let nothing: null = null;
let notDefined: undefined = undefined;

// 示例:类型检查
// name = 123; // 错误:不能将类型“number”分配给类型“string”

2.2 任意类型(Any)

any 类型允许任意值,适合临时禁用类型检查。

let anything: any = "Hello";
anything = 42; // 合法
anything = { name: "Bob" }; // 合法

2.3 未知类型(Unknown)

unknown 是更安全的 any,需要类型断言或检查。

let value: unknown = "Hello";
if (typeof value === "string") {
  console.log(value.toUpperCase()); // 合法
}
// console.log(value.toUpperCase()); // 错误:类型“unknown”上不存在“toUpperCase”

2.4 数组(Arrays)

数组可以通过类型注解定义。

let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];

// 示例:数组操作
numbers.push(4); // 合法
// numbers.push("5"); // 错误:不能将类型“string”分配给类型“number”

2.5 元组(Tuples)

元组允许定义固定长度和类型的数组。

let tuple: [string, number] = ["Alice", 25];
// tuple[0] = 123; // 错误:不能将类型“number”分配给类型“string”
// tuple.push("Bob"); // 注意:元组允许 push,但可能破坏类型安全

2.6 枚举(Enums)

枚举定义一组命名常量,支持数字和字符串值。

enum Color {
  Red = 1,
  Green,
  Blue,
}
let color: Color = Color.Green; // 2
console.log(Color[2]); // "Green"

// 字符串枚举
enum Direction {
  Up = "UP",
  Down = "DOWN",
}
let dir: Direction = Direction.Up; // "UP"

3. 对象类型

3.1 接口(Interfaces)

接口用于描述对象形状。

interface Person {
  name: string;
  age: number;
  isStudent?: boolean; // 可选属性
  readonly id: number; // 只读属性
}

let person: Person = {
  name: "Alice",
  age: 25,
  id: 1,
};

// person.id = 2; // 错误:无法分配到“id”,因为它是只读属性

3.2 类型别名(Type Aliases)

类型别名与接口类似,但更灵活,支持联合类型等。

type Point = {
  x: number;
  y: number;
};

let point: Point = { x: 10, y: 20 };

3.3 联合类型(Union Types)

允许变量具有多种类型。

let id: string | number = "123";
id = 123; // 合法
// id = true; // 错误:不能将类型“boolean”分配给类型“string | number”

3.4 交叉类型(Intersection Types)

组合多个类型。

type Named = { name: string };
type Aged = { age: number };
type Person = Named & Aged;

let person: Person = { name: "Alice", age: 25 };

4. 函数

4.1 函数类型

可以为函数参数和返回值指定类型。

function add(a: number, b: number): number {
  return a + b;
}

// 函数表达式
let multiply: (x: number, y: number) => number = (x, y) => x * y;

4.2 可选参数与默认值

参数可以是可选的或有默认值。

function greet(name: string, greeting: string = "Hello"): string {
  return `${greeting}, ${name}!`;
}

console.log(greet("Alice")); // "Hello, Alice!"
console.log(greet("Bob", "Hi")); // "Hi, Bob!"

4.3 函数重载

支持定义多个函数签名。

function parse(input: string): string;
function parse(input: number): number;
function parse(input: string | number): string | number {
  return input;
}

let str = parse("test"); // string
let num = parse(123); // number

5. 高级类型

5.1 泛型(Generics)

泛型允许创建可重用的类型。

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

let str = identity<string>("Hello"); // string
let num = identity<number>(42); // number

5.2 条件类型(Conditional Types)

根据条件选择类型。

type IsString<T> = T extends string ? "string" : "not string";

type A = IsString<string>; // "string"
type B = IsString<number>; // "not string"

5.3 工具类型(Utility Types)

TypeScript 提供内置工具类型,如 PartialRequired 等。

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

let partialUser: Partial<User> = { name: "Alice" }; // 部分属性
let requiredUser: Required<User> = { name: "Bob", age: 30 }; // 所有属性必填

5.4 satisfies 运算符(TypeScript 4.9+)

确保类型匹配但保留具体类型。

type Palette = {
  [key: string]: string | number[];
};

const palette = {
  red: "#FF0000",
  blue: [0, 0, 255],
} satisfies Palette;

// palette.red 是 string 类型,而不是 string | number[]

6. 模块与命名空间

6.1 模块(Modules)

支持 ES 模块和 CommonJS。

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

// main.ts
import { add } from "./math";
console.log(add(2, 3)); // 5

6.2 命名空间(Namespaces)

用于组织代码,避免命名冲突。

namespace Geometry {
  export interface Point {
    x: number;
    y: number;
  }

  export function distance(p1: Point, p2: Point): number {
    return Math.sqrt((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2);
  }
}

let p1: Geometry.Point = { x: 0, y: 0 };
let p2: Geometry.Point = { x: 3, y: 4 };
console.log(Geometry.distance(p1, p2)); // 5

7. 与 JavaScript 互操作

7.1 声明文件(Declaration Files)

为现有 JavaScript 库提供类型定义。

// my-lib.d.ts
declare module "my-lib" {
  export function doSomething(value: string): string;
}

// main.ts
import { doSomething } from "my-lib";
let result = doSomething("test"); // 合法

7.2 类型断言(Type Assertions)

强制指定类型。

let value: any = "Hello";
let strLength: number = (value as string).length; // 合法

8. 装饰器(Decorators,实验性功能)

装饰器用于元编程,需在 tsconfig.json 中启用 experimentalDecorators

function logged(target: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${key} with`, args);
    return original.apply(this, args);
  };
}

class Calculator {
  @logged
  add(a: number, b: number): number {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3); // 输出:Calling add with [2, 3]

9. 工具与生态

9.1 Visual Studio Code 支持

VS Code 内置 TypeScript 支持,提供智能提示、错误检查等。

// 鼠标悬停即可查看类型信息
let name: string = "Alice";

9.2 ESLint 与 TypeScript

使用 typescript-eslint 增强代码质量。

npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
// .eslintrc.json
{
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint"],
  "rules": {
    "@typescript-eslint/no-unused-vars": "error"
  }
}

9.3 TypeDoc 生成文档

使用 TypeDoc 生成 TypeScript 项目文档。

npm install --save-dev typedoc
typedoc --out docs src

10. React 与 TypeScript

10.1 函数组件

为 React 函数组件定义 props 类型。

import React from "react";

interface Props {
  name: string;
  age?: number;
}

const MyComponent: React.FC<Props> = ({ name, age }) => {
  return (
    <div>
      Hello, {name}! {age && `Age: ${age}`}
    </div>
  );
};

10.2 Hooks

TypeScript 自动推断 Hooks 类型。

import React, { useState, useEffect } from "react";

const Counter: React.FC = () => {
  const [count, setCount] = useState<number>(0);

  useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]);

  return <button onClick={() => setCount(count + 1)}>Increment</button>;
};

11. Node.js 与 TypeScript

11.1 使用 tsx 运行

使用 tsx 运行 TypeScript 文件。

npm install --save-dev tsx
npx tsx src/index.ts

11.2 配置 tsconfig.json

推荐 Node.js 项目的配置:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "outDir": "./dist",
    "strict": true
  }
}

12. 最新特性(TypeScript 5.8)

12.1 改进的类型推断

TypeScript 5.8 增强了类型推断,尤其是在对象解构时。

const { data } = { data: { name: "Alice" } };
console.log(data.name); // 推断为 string

12.2 实验性类型转换

Node.js 支持 --experimental-transform-types 处理非可擦除语法。

enum Status {
  Active = "ACTIVE",
  Inactive = "INACTIVE",
}

let status: Status = Status.Active; // 合法

13. 调试与错误处理

13.1 错误提示

TypeScript 在编译时捕获类型错误。

let num: number = 42;
// num = "Hello"; // 错误:不能将类型“string”分配给类型“number”

13.2 调试

在 VS Code 中配置 launch.json 调试 TypeScript。

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "program": "${workspaceFolder}/dist/index.js",
      "preLaunchTask": "tsc: build - tsconfig.json"
    }
  ]
}

14. 最佳实践

  • 启用严格模式:在 tsconfig.json 中设置 "strict": true
  • 使用类型别名或接口:为复杂类型定义清晰的结构。
  • 避免 any:优先使用 unknown 或具体类型。
  • 模块化:将代码组织成模块,增强可维护性。

15. 资源与进一步学习