Skip to content

Commit 927b7cd

Browse files
fix: Type checker does not detect a signature mismatch
Fixes: #2727
1 parent eedf306 commit 927b7cd

File tree

4 files changed

+42
-21
lines changed

4 files changed

+42
-21
lines changed

src/compiler.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6609,17 +6609,18 @@ export class Compiler extends DiagnosticEmitter {
66096609
for (let i = 0, k = overrideInstances.length; i < k; ++i) {
66106610
let overrideInstance = overrideInstances[i];
66116611
if (!overrideInstance.is(CommonFlags.Compiled)) continue; // errored
6612-
let overrideType = overrideInstance.type;
6613-
let originalType = instance.type;
6614-
if (!overrideType.isAssignableTo(originalType)) {
6612+
6613+
let overrideSignature = overrideInstance.signature;
6614+
let originalSignature = instance.signature;
6615+
6616+
if (!overrideSignature.isAssignableTo(originalSignature, true)) {
66156617
this.error(
66166618
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
6617-
overrideInstance.identifierNode.range, overrideType.toString(), originalType.toString()
6619+
overrideInstance.identifierNode.range, overrideSignature.toString(), originalSignature.toString()
66186620
);
66196621
continue;
66206622
}
66216623
// TODO: additional optional parameters are not permitted by `isAssignableTo` yet
6622-
let overrideSignature = overrideInstance.signature;
66236624
let overrideParameterTypes = overrideSignature.parameterTypes;
66246625
let overrideNumParameters = overrideParameterTypes.length;
66256626
let paramExprs = new Array<ExpressionRef>(1 + overrideNumParameters);

src/types.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,22 +1051,14 @@ export class Signature {
10511051
isAssignableTo(target: Signature, checkCompatibleOverride: bool = false): bool {
10521052
let thisThisType = this.thisType;
10531053
let targetThisType = target.thisType;
1054-
if (checkCompatibleOverride) {
1055-
// check kind of `this` type
1056-
if (thisThisType) {
1057-
if (!targetThisType || !thisThisType.canExtendOrImplement(targetThisType)) {
1058-
return false;
1059-
}
1060-
} else if (targetThisType) {
1061-
return false;
1062-
}
1063-
} else {
1064-
// check `this` type (invariant)
1065-
if (thisThisType) {
1066-
if (targetThisType != targetThisType) return false;
1067-
} else if (targetThisType) {
1068-
return false;
1069-
}
1054+
1055+
if (thisThisType && targetThisType) {
1056+
const compatibleThisType = checkCompatibleOverride
1057+
? thisThisType.canExtendOrImplement(targetThisType)
1058+
: targetThisType.isAssignableTo(thisThisType);
1059+
if (!compatibleThisType) return false;
1060+
} else if (thisThisType || targetThisType) {
1061+
return false;
10701062
}
10711063

10721064
// check rest parameter
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"asc_flags": [],
3+
"stderr": [
4+
"TS2322: Type '() => void' is not assignable to type '(this: class-member-function-as-parameter/A) => void'.",
5+
"TS2322: Type '(this: class-member-function-as-parameter/B) => void' is not assignable to type '(this: class-member-function-as-parameter/A) => void'.",
6+
"EOF"
7+
]
8+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class A {
2+
foo(): void { }
3+
}
4+
5+
class B extends A {
6+
foo(): void { }
7+
}
8+
9+
function foo(): void { }
10+
11+
function consumeA(callback: (this: A) => void): void { }
12+
function consumeB(callback: (this: B) => void): void { }
13+
14+
const a = new A();
15+
const b = new B();
16+
17+
consumeB(a.foo); // shouldn't error
18+
consumeA(foo); // should error
19+
consumeA(b.foo); // should error
20+
ERROR("EOF");

0 commit comments

Comments
 (0)