TypeScript继承接口作为函数参数时赋值报错的原因是什么
核心原因:TypeScript 函数参数遵循逆变的兼容性规则,和普通变量的协变规则不同
这是 TypeScript 为了避免运行时类型错误做的强制限制,具体逻辑如下:
- 普通变量赋值的协变规则很好理解:
B是A的子类型,包含A定义的所有属性,把B类型的值赋值给A类型变量时,任何对A属性的访问都不会出错,所以是合法的。 - 函数参数的逆变规则刚好相反:如果要把类型为
BFUNC的函数赋值给AFUNC类型的变量,要求BFUNC的参数类型必须是AFUNC参数类型的父类型,而不是子类型。
你可以代入实际运行场景理解这个限制的必要性:
如果 TS 允许 aGetter = bGetter 赋值成立,按照 AFUNC 的类型定义,你后续可以合法传入一个纯 A 类型的参数调用 aGetter,比如:
aGetter({foo: "test"})
而此时实际运行的是 bGetter 的逻辑,bGetter 要求参数必须是包含 bar 属性的 B 类型,一旦 bGetter 内部访问了参数的 bar 属性,就会出现运行时报错。TS 正是提前识别到了这个风险,才会在赋值阶段就抛出类型错误。
补充函数类型兼容性的完整判断规则:
函数 X 可赋值给函数 Y 需同时满足两个条件:
X的每个参数类型,都是Y对应参数类型的父类型(Y的参数可以直接赋值给X的参数)X的返回值类型,是Y返回值类型的子类型(X的返回值可以直接赋值给Y的返回值)
你当前场景中 BFUNC 的参数是 B(A 的子类型),不满足第一条要求,因此会被 TS 判定为非法赋值。
内容的提问来源于stack exchange,提问作者Thaledric
相关产品推荐
相关产品推荐

