TypeScript中父子类参数方法无法赋值的原因咨询
TypeScript函数参数类型兼容问题解析
问题代码
class Parent { id: string = '' } class Child extends Parent{ name: string = '' } const fails: (created: Parent) => void = (created: Child) => { return }; const failsToo: ({ created }: { created: Parent }) => void = ({ created }: { created: Child }) => { return };
报错信息
Type '(created: Child) => void' is not assignable to type '(created: Parent) => void'. Types of parameters 'created' and 'created' are incompatible. Property 'name' is missing in type 'Parent' but required in type 'Child'
用户疑问
我对此感到困惑:代码是试图将参数为Child的方法赋值给参数为Parent的变量,而Child是Parent的超集,应该兼容,但错误提示却像是在尝试将Parent赋值给Child,请问我哪里理解错了?
问题解析
你搞反了函数参数的类型兼容逻辑——函数参数的类型兼容是逆变的,不是协变的。
简单说:当你把一个函数赋值给类型为(p: Parent) => void的变量时,这个变量的使用者有权传入任意Parent类型的实例(包括Parent本身,不一定是Child)。但你赋值的函数(created: Child) => void却要求参数必须是Child类型,它内部可能会访问created.name这个Parent没有的属性。如果真允许这么赋值,当使用者传入一个纯Parent实例时,函数里访问name就会直接报错,TypeScript提前帮你拦截了这个风险。
举个实际场景的例子:
const myFunc: (created: Parent) => void = (created: Child) => { // 这里如果写了console.log(created.name),调用时传入Parent实例就会崩溃 }; // 使用者完全合法的调用:传入Parent实例 myFunc(new Parent());
所以TypeScript的错误提示是对的:你试图把一个要求参数是Child的函数,赋值给一个接受Parent参数的变量,这意味着变量的使用者可能传入Parent类型的值,而函数无法处理这种情况——相当于把Parent类型的值塞给了期望Child类型的参数位置,自然会提示Parent缺少Child的name属性。
内容的提问来源于stack exchange,提问作者Giovanii Mirko Terrazas
相关产品推荐
相关产品推荐

