Skip to content

TypeScript 实战指南

TypeScript 是 JavaScript 的超集,为 JavaScript 添加了类型系统。本文将介绍 TypeScript 的核心概念和实战技巧。

1. 类型系统

TypeScript 的核心特性是其类型系统,它可以帮助我们在编译时发现错误。

基本类型

typescript
// 基本类型
let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";
let list: number[] = [1, 2, 3];
let tuple: [string, number] = ["hello", 10];
enum Color {Red, Green, Blue};
let c: Color = Color.Green;
let notSure: any = 4;
let nothing: void = undefined;
let nullValue: null = null;
let undefinedValue: undefined = undefined;
let object: object = {name: "John"};

接口

接口用于定义对象的结构。

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

let person: Person = {
  name: "John",
  age: 30,
  id: 123
};

泛型

泛型允许我们编写可重用的组件。

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

let output = identity<string>("myString");
let output2 = identity<number>(100);

2. 高级类型

联合类型

联合类型表示一个值可以是几种类型中的一种。

typescript
let value: string | number;
value = "hello";
value = 42;

交叉类型

交叉类型表示一个值同时具有多种类型的特性。

typescript
interface A {
  a: number;
}

interface B {
  b: string;
}

let value: A & B = {
  a: 1,
  b: "hello"
};

类型守卫

类型守卫用于在运行时检查类型。

typescript
function isString(value: any): value is string {
  return typeof value === "string";
}

function processValue(value: string | number) {
  if (isString(value)) {
    // 这里 value 被推断为 string 类型
    console.log(value.toUpperCase());
  } else {
    // 这里 value 被推断为 number 类型
    console.log(value.toFixed(2));
  }
}

3. 模块系统

TypeScript 使用 ES 模块系统。

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

export interface Calculator {
  add(a: number, b: number): number;
  subtract(a: number, b: number): number;
}

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

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

class SimpleCalculator implements Calculator {
  add(a: number, b: number): number {
    return a + b;
  }
  
  subtract(a: number, b: number): number {
    return a - b;
  }
}

4. 接口与类型别名

接口

接口主要用于定义对象的结构。

typescript
interface User {
  id: number;
  name: string;
  email: string;
}

interface User {
  age?: number; // 接口可以被合并
}

类型别名

类型别名可以定义任何类型。

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

// 类型别名不能被合并
type User = {
  age: number; // 错误:重复的类型别名
};

5. 类型断言

类型断言用于告诉 TypeScript 编译器我们知道变量的类型。

typescript
// 尖括号语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

// as 语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

6. 枚举

枚举用于定义一组命名常量。

typescript
// 数字枚举
enum Direction {
  Up = 1,
  Down,
  Left,
  Right
}

// 字符串枚举
enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}

// 常量枚举
const enum Direction {
  Up, Down, Left, Right
}

7. 类

TypeScript 支持面向对象编程。

typescript
class Person {
  private name: string;
  protected age: number;
  public email: string;
  
  constructor(name: string, age: number, email: string) {
    this.name = name;
    this.age = age;
    this.email = email;
  }
  
  getName(): string {
    return this.name;
  }
  
  setName(name: string): void {
    this.name = name;
  }
}

class Employee extends Person {
  private employeeId: number;
  
  constructor(name: string, age: number, email: string, employeeId: number) {
    super(name, age, email);
    this.employeeId = employeeId;
  }
  
  getEmployeeId(): number {
    return this.employeeId;
  }
}

8. 装饰器

装饰器用于修改类、方法、属性或参数的行为。

typescript
// 类装饰器
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;
  }
}

// 方法装饰器
function enumerable(value: boolean) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    descriptor.enumerable = value;
  };
}

class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
  
  @enumerable(false)
  greet() {
    return "Hello, " + this.greeting;
  }
}

9. 配置文件

TypeScript 使用 tsconfig.json 文件来配置编译选项。

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

10. 与框架集成

与 React 集成

tsx
import React, { useState } from 'react';

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

const UserComponent: React.FC<Props> = ({ name, age }) => {
  const [count, setCount] = useState<number>(0);
  
  return (
    <div>
      <h1>{name}</h1>
      <p>Age: {age}</p>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

与 Vue 集成

vue
<template>
  <div>
    <h1>{{ user.name }}</h1>
    <p>Age: {{ user.age }}</p>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

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

export default defineComponent({
  name: 'UserComponent',
  props: {
    user: {
      type: Object as () => User,
      required: true
    }
  }
});
</script>

11. 最佳实践

  1. 使用严格模式:在 tsconfig.json 中设置 "strict": true
  2. 明确类型:为变量、函数参数和返回值指定类型
  3. 使用接口:定义对象的结构
  4. 使用泛型:编写可重用的代码
  5. 使用类型守卫:在运行时检查类型
  6. 避免使用 any:尽量使用具体的类型
  7. 使用枚举:定义一组相关的常量
  8. 使用装饰器:增强类和方法的功能
  9. 合理使用类型断言:仅在必要时使用
  10. 保持代码风格一致:使用 ESLint 和 Prettier

12. 性能优化

  1. 使用 const 枚举:减少运行时开销
  2. 使用 readonly:防止不必要的修改
  3. 使用类型守卫:避免运行时类型检查
  4. 合理使用泛型:避免过度使用泛型
  5. 使用模块:按需导入模块
  6. 使用 tree shaking:移除未使用的代码

13. 常见问题

类型错误

typescript
// 错误:类型 'string' 不能赋值给类型 'number'
let num: number = "123";

// 正确
let num: number = parseInt("123");

模块解析

typescript
// 错误:找不到模块 './math'
import { add } from './math';

// 正确:添加 .ts 扩展名或配置模块解析
import { add } from './math.ts';

类型定义

typescript
// 错误:找不到名称 'Window'
const window: Window = globalThis;

// 正确:安装类型定义
// npm install --save-dev @types/node

14. 工具推荐

  1. tsc:TypeScript 编译器
  2. ts-node:直接运行 TypeScript 文件
  3. ESLint:代码检查
  4. Prettier:代码格式化
  5. VS Code:TypeScript 支持
  6. TypeScript Playground:在线 TypeScript 编辑器

15. 总结

TypeScript 为 JavaScript 添加了类型系统,使我们能够编写更加安全、可维护的代码。通过学习和使用 TypeScript,我们可以提高代码质量,减少运行时错误,提高开发效率。

TypeScript 已经成为前端开发的主流语言,许多大型项目和框架都在使用 TypeScript。掌握 TypeScript 是现代前端开发者的必备技能。