Skip to content

TS 新手常见错误与避坑

类型不匹配

常见场景

  • 变量类型与赋值类型不一致
  • 函数参数类型与调用时传入类型不匹配
  • 函数返回值类型与实际返回值不匹配

错误示例

typescript
// 错误:类型不匹配
let age: number = "18"; // 类型 'string' 不能赋值给类型 'number'

// 错误:函数参数类型不匹配
function greet(name: string) {
  console.log(`Hello, ${name}!`);
}
greet(18); // 类型 'number' 不能赋值给类型 'string'

// 错误:函数返回值类型不匹配
function add(a: number, b: number): number {
  return "result" + (a + b); // 类型 'string' 不能赋值给类型 'number'
}

解决方案

  • 明确指定变量类型
  • 检查函数参数和返回值类型
  • 使用类型断言进行类型转换(谨慎使用)
  • 利用 TypeScript 的类型推断

对象缺少属性

常见场景

  • 创建对象时缺少必填属性
  • 访问对象不存在的属性
  • 函数参数对象缺少必要属性

错误示例

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

// 错误:缺少必填属性
const user: User = {
  name: "John"
  // 缺少 age 和 email
};

// 错误:访问不存在的属性
const user: User = {
  name: "John",
  age: 30,
  email: "john@example.com"
};
console.log(user.phone); // 属性 'phone' 不存在于类型 'User' 上

解决方案

  • 使用可选属性(?
  • 使用默认值
  • 使用类型守卫检查属性存在性
  • 确保对象结构与接口定义一致

函数参数错误

常见场景

  • 函数参数数量不匹配
  • 可选参数位置错误
  • 剩余参数使用错误

错误示例

typescript
// 错误:参数数量不匹配
function add(a: number, b: number): number {
  return a + b;
}
add(1, 2, 3); // 应有 2 个参数,但获得 3 个

// 错误:可选参数位置错误
function greet(name: string, age?: number, address: string): string {
  return `Hello, ${name}!`;
}
// 可选参数必须放在必选参数之后

// 错误:剩余参数使用错误
function sum(...numbers: number): number {
  return numbers.reduce((a, b) => a + b, 0);
}
// 剩余参数必须是数组类型

解决方案

  • 确保参数数量与函数定义一致
  • 可选参数放在必选参数之后
  • 剩余参数使用数组类型
  • 使用默认参数值

无法推断类型

常见场景

  • 复杂对象类型推断失败
  • 泛型类型推断失败
  • 联合类型推断不明确

错误示例

typescript
// 错误:复杂对象类型推断失败
const user = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "New York"
  }
};
// TypeScript 可以推断基本类型,但复杂嵌套对象可能需要显式类型

// 错误:泛型类型推断失败
function identity<T>(arg: T): T {
  return arg;
}
const result = identity({ name: "John" });
// 类型被推断为 { name: string },但可能需要更精确的类型

// 错误:联合类型推断不明确
let value: string | number;
value = "hello";
value.toUpperCase(); // 类型 'string | number' 上不存在属性 'toUpperCase'

解决方案

  • 显式指定类型注解
  • 使用类型断言
  • 使用类型守卫
  • 为复杂对象定义接口

any 滥用问题

常见场景

  • 随意使用 any 类型
  • 禁用 TypeScript 的类型检查
  • 失去 TypeScript 的类型安全优势

错误示例

typescript
// 错误:滥用 any
let data: any = fetch("https://api.example.com/data");
data = data.json();
data.users.forEach(user => console.log(user.name));
// 失去类型检查,可能运行时错误

// 错误:函数返回 any
function getData(): any {
  return { name: "John", age: 30 };
}
const user = getData();
user.address.street; // 运行时错误,address 不存在

解决方案

  • 尽量避免使用 any
  • 使用 unknown 类型代替 any
  • 为复杂类型定义接口
  • 利用 TypeScript 的类型推断

编译报错排查

常见编译错误

  • 类型不匹配
  • 缺少属性
  • 访问不存在的属性
  • 函数参数错误
  • 循环依赖

错误信息解读

  1. 类型不匹配

    Type 'string' is not assignable to type 'number'.
    • 原因:尝试将字符串赋值给数字类型
    • 解决方案:检查类型注解,确保类型一致
  2. 缺少属性

    Property 'age' is missing in type '{ name: string; }' but required in type 'User'.
    • 原因:创建对象时缺少必填属性
    • 解决方案:添加缺少的属性,或使用可选属性
  3. 访问不存在的属性

    Property 'phone' does not exist on type 'User'.
    • 原因:访问对象不存在的属性
    • 解决方案:检查属性名,或使用可选链操作符
  4. 函数参数错误

    Expected 2 arguments, but got 3.
    • 原因:函数调用时参数数量不匹配
    • 解决方案:检查函数定义,确保参数数量一致
  5. 循环依赖

    Circular dependency detected.
    • 原因:模块之间相互引用形成循环
    • 解决方案:重构代码,消除循环依赖

排查技巧

  • 仔细阅读错误信息
  • 检查类型注解和接口定义
  • 使用 TypeScript 编译器的错误定位
  • 利用 IDE 的类型提示和错误检查
  • 逐步排查,从简单到复杂

最佳实践

  1. 使用严格模式

    • 在 tsconfig.json 中启用 strict: true
    • 开启所有严格类型检查选项
  2. 合理使用类型

    • 为所有变量和函数添加类型注解
    • 使用接口定义复杂数据结构
    • 利用泛型提高代码复用性
  3. 避免 any 类型

    • 使用 unknown 类型代替 any
    • 为第三方库添加类型定义
    • 逐步消除代码中的 any
  4. 使用类型守卫

    • 对联合类型使用类型守卫
    • 确保类型安全的类型转换
  5. 代码组织

    • 按功能模块化代码
    • 合理使用命名空间和模块
    • 保持类型定义的一致性

© 2026 编程马·菜鸟教程 版权所有