You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Compile does not produce an error when parameters in overriding class method in child class have narrower type than the parameters of this method in the parent class #58122
// The code below is compiled without error even with --strictFunctionTypes// although it produces an error while being executedinterfaceI{a: number;}interfaceJextendsI{b: string;}classA{publicm(x: I): number{returnx.a;};}classBextendsA{// This overrides method "m" in class "A".// Such override must be forbidden,// because it narrows down the parameter type of method "m" compared to parent class,// which causes an error when object of class "B" is used instead of object of class "A".publicm(x: J): number{returnx.a+x.b.length;};}functionf(x: A): number{constp: I={a: 1};returnx.m(p);}constb: B=newB();// Function "f" accepts argument of class "B" also because "B" is a subclass of "A",// but it produces "Cannot read properties of undefined (reading 'length')"constx: number=f(b);
🙁 Actual behavior
The code above is compiled without an error even with --strictFunctionTypes, but when executed it gives Cannot read properties of undefined (reading 'length') error. Bug here is that TypeScript compiler does not recognize an error in the code above.
🙂 Expected behavior
I expect that code above should produce a compilation error (see additional information below).
Additional information about the issue
Below is the similar code, but if compiled with --strictFunctionTypes TypeScript gives an error, which is expected. The difference of the code below from the code above is that in the above code m is a method of classes, but in the code below m is a member of classes.
// The code below has compilation error with --strictFunctionTypes// and has no compilation error without --strictFunctionTypes// This is expected behaviour.//// Error witht --strictFunctionTypes:// Property 'm' in type 'B' is not assignable to the same property in base type 'A'.// Type '(x: J) => number' is not assignable to type '(x: I) => number'.// Types of parameters 'x' and 'x' are incompatible.// Property 'b' is missing in type 'I' but required in type 'J'.interfaceI{a: number;}interfaceJextendsI{b: string;}classA{publicm=(x: I)=>{returnx.a;};}classBextendsA{publicm=(x: J)=>{// <-- here is a compilation errorreturnx.a+x.b.length;};}
I wonder why --strictFunctionTypes enables contravariance for function parameters, but not covariance? This doesn't seem logical, because as it was shown above it allows a runtime error which could be caught at compile time.
This is working as intended. There's even a section in the FAQ about this, and the behavior is required for some types (e.g. Arrays). Note that strictFunctionTypes applies to functions, not methods.
Activity
MartinJohns commentedon Apr 8, 2024
This is working as intended. There's even a section in the FAQ about this, and the behavior is required for some types (e.g. Arrays). Note that
strictFunctionTypesapplies to functions, not methods.edrennikov commentedon Apr 8, 2024
But as provided in the example above there is obviously an error in the code which can be caught at compile time.
MartinJohns commentedon Apr 8, 2024
Yes, that's true. But it's still working as intended. TypeScripts type system is not fully sound (and it's not intended to).
Your intended change would break a whole lot of other stuff. See also #57783 for more information.
edrennikov commentedon Apr 8, 2024
That's sad 😕 Another broken dream in software development 🥲