为何TypeScript中func可接收X2类型?子类方法参数不兼容父类
这是因为TypeScript对类的方法参数默认采用了**双向协变(Bivariance)**的类型检查规则,而非严格的函数类型逆变规则,导致子类收窄方法参数类型的操作未被检测为错误。
核心规则说明
在严格的类型安全体系中,函数/方法的参数类型遵循逆变原则:子类方法的参数类型必须等于或宽于父类的参数类型(比如父类用F1,子类可以用F1或更宽泛的类型),这样才能保证用父类类型引用子类实例时,传入父类允许的参数不会触发类型不兼容问题。
但TypeScript默认对类的方法启用了双向协变——允许子类方法的参数类型既可以宽于、也可以窄于父类的参数类型。这是为了兼容JavaScript中常见的编程模式(比如数组forEach回调常被传入更具体的参数类型)。
如何触发预期的类型错误
若需要严格的类型检查,启用--strictFunctionTypes编译选项即可。开启后,TypeScript会对函数类型(包括类的方法)应用严格的逆变规则,此时X2的index方法会直接抛出错误:
Property 'index' in type 'X2' is not assignable to the same property in base type 'X1'.
Type '(param: F2) => void' is not assignable to type '(param: F1) => void'.
Types of parameters 'param' and 'param' are incompatible.
Type 'F1' is not assignable to type 'F2'.
运行时风险提示
虽然TypeScript默认未报错,但这段代码存在明确的运行时隐患:当func传入X2实例并调用x.index(f1)时,f1是F1实例而非F2,若X2.index中访问param.value2会直接抛出undefined相关的错误,因为F1并没有value2属性。
内容的提问来源于stack exchange,提问作者kennarddh

