You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript箭头函数参数类型不兼容报错原因及解决方法

为什么TypeScript中箭头函数参数缩小类型会报错?

先看你的核心问题代码:

interface Person {
  name: string;
}

type ObjToString = (obj: object) => string;

// 此处报错:类型'(obj: Person) => string'不能赋值给类型'ObjToString'
const personToString: ObjToString = (obj: Person) => obj.name;

错误提示显示Person类型的参数与object类型不兼容,因为{}缺少name属性,但你却能正常将Person变量赋值给object变量:

let obj: object;
const person: Person = { name: "Tom" };
obj = person; // 完全正常

原因:变量协变 vs 函数参数逆变

TypeScript的类型兼容性规则中存在两种核心逻辑:

  • 普通对象类型是协变的:子类型可以赋值给父类型。Person是object的子类型,所以person能赋值给obj。
  • 函数参数类型是逆变的:父类型可以赋值给子类型(与协变逻辑相反)。ObjToString要求函数能接受任意object类型的参数,但你定义的函数只接受Person类型——如果有人调用personToString({}),函数会试图访问obj.name,但空对象没有该属性,直接触发运行时错误。TypeScript提前拦截了这个风险,因此抛出报错。

解决方法

根据你的实际需求,可以选择以下几种方案:

1. 调整函数类型定义,明确参数为Person

如果函数本来就只处理Person类型,直接修改ObjToString的参数类型:

type ObjToString = (obj: Person) => string;
const personToString: ObjToString = (obj) => obj.name; // 正常编译

2. 在函数内部做类型守卫,兼容所有object

如果必须保留ObjToString的object参数类型,在函数内部添加类型判断:

const personToString: ObjToString = (obj) => {
  if ('name' in obj && typeof obj.name === 'string') {
    return obj.name;
  }
  return 'Unknown'; // 处理非Person类型的情况
};

3. 使用类型断言(谨慎使用)

如果你能保证调用函数时只会传入Person类型,可以用类型断言绕过检查:

const personToString: ObjToString = (obj) => (obj as Person).name;

注意:这种方式会跳过TypeScript的类型检查,一旦传入非Person对象,运行时会报错,仅在你能完全控制调用场景时使用。

4. 用泛型约束参数类型

如果希望函数能处理任意带name属性的对象,使用泛型约束:

type ObjToString<T extends { name: string }> = (obj: T) => string;
const personToString: ObjToString<Person> = (obj) => obj.name;

内容的提问来源于stack exchange,提问作者AnsonH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:10:12