Description
🔎 Search Terms
[class ](is:issue is:open label:Bug inherit)
🕗 Version & Regression Information
- This is a crash
- This changed between versions ______ and _______
- This changed in commit or PR _______
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
strictFunctionTypes
here - I was unable to test this on prior versions because _______
⏯ Playground Link
💻 Code
// The code below is compiled without error even with --strictFunctionTypes
// although it produces an error while being executed
interface I {
a: number;
}
interface J extends I {
b: string;
}
class A {
public m(x: I): number {
return x.a;
};
}
class B extends A {
// 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".
public m(x: J): number {
return x.a + x.b.length;
};
}
function f(x: A): number {
const p: I = {a: 1};
return x.m(p);
}
const b: B = new B();
// 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')"
const x: 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'.
interface I {
a: number;
}
interface J extends I {
b: string;
}
class A {
public m = (x: I) => {
return x.a;
};
}
class B extends A {
public m = (x: J) => { // <-- here is a compilation error
return x.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.