Skip to content

Commit ae62da9

Browse files
Fixes microsoft#35735: Avoids listing missing properties for types with only call/construct signatures (microsoft#40973)
* Fixes microsoft#35735 * fixes microsoft#35735 * PR feedback Co-authored-by: Wesley Wigham <wewigham@microsoft.com>
1 parent 5f9f9e3 commit ae62da9

20 files changed

+196
-73
lines changed

src/compiler/checker.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -19996,7 +19996,7 @@ namespace ts {
1999619996
const requireOptionalProperties = (relation === subtypeRelation || relation === strictSubtypeRelation) && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source) && !isTupleType(source);
1999719997
const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false);
1999819998
if (unmatchedProperty) {
19999-
if (reportErrors) {
19999+
if (reportErrors && shouldReportUnmatchedPropertyError(source, target)) {
2000020000
reportUnmatchedProperty(source, target, unmatchedProperty, requireOptionalProperties);
2000120001
}
2000220002
return Ternary.False;
@@ -20154,6 +20154,20 @@ namespace ts {
2015420154
return result;
2015520155
}
2015620156

20157+
function shouldReportUnmatchedPropertyError(source: Type, target: Type): boolean {
20158+
const typeCallSignatures = getSignaturesOfStructuredType(source, SignatureKind.Call);
20159+
const typeConstructSignatures = getSignaturesOfStructuredType(source, SignatureKind.Construct);
20160+
const typeProperties = getPropertiesOfObjectType(source);
20161+
if ((typeCallSignatures.length || typeConstructSignatures.length) && !typeProperties.length) {
20162+
if ((getSignaturesOfType(target, SignatureKind.Call).length && typeCallSignatures.length) ||
20163+
(getSignaturesOfType(target, SignatureKind.Construct).length && typeConstructSignatures.length)) {
20164+
return true; // target has similar signature kinds to source, still focus on the unmatched property
20165+
}
20166+
return false;
20167+
}
20168+
return true;
20169+
}
20170+
2015720171
function reportIncompatibleCallSignatureReturn(siga: Signature, sigb: Signature) {
2015820172
if (siga.parameters.length === 0 && sigb.parameters.length === 0) {
2015920173
return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target));

tests/baselines/reference/arrayAssignmentTest1.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ tests/cases/compiler/arrayAssignmentTest1.ts(76,1): error TS2322: Type 'C1[]' is
2020
Property 'CM3M1' is missing in type 'C1' but required in type 'C3'.
2121
tests/cases/compiler/arrayAssignmentTest1.ts(77,1): error TS2322: Type 'I1[]' is not assignable to type 'C3[]'.
2222
Property 'CM3M1' is missing in type 'I1' but required in type 'C3'.
23-
tests/cases/compiler/arrayAssignmentTest1.ts(79,1): error TS2740: Type '() => C1' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
23+
tests/cases/compiler/arrayAssignmentTest1.ts(79,1): error TS2322: Type '() => C1' is not assignable to type 'any[]'.
2424
tests/cases/compiler/arrayAssignmentTest1.ts(80,1): error TS2740: Type '{ one: number; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
2525
tests/cases/compiler/arrayAssignmentTest1.ts(82,1): error TS2740: Type 'C1' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
2626
tests/cases/compiler/arrayAssignmentTest1.ts(83,1): error TS2740: Type 'C2' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
@@ -152,7 +152,7 @@ tests/cases/compiler/arrayAssignmentTest1.ts(85,1): error TS2740: Type 'I1' is m
152152

153153
arr_any = f1; // should be an error - is
154154
~~~~~~~
155-
!!! error TS2740: Type '() => C1' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
155+
!!! error TS2322: Type '() => C1' is not assignable to type 'any[]'.
156156
arr_any = o1; // should be an error - is
157157
~~~~~~~
158158
!!! error TS2740: Type '{ one: number; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.

tests/baselines/reference/arrayAssignmentTest2.errors.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ tests/cases/compiler/arrayAssignmentTest2.ts(48,1): error TS2322: Type 'C1[]' is
44
Property 'CM3M1' is missing in type 'C1' but required in type 'C3'.
55
tests/cases/compiler/arrayAssignmentTest2.ts(49,1): error TS2322: Type 'I1[]' is not assignable to type 'C3[]'.
66
Property 'CM3M1' is missing in type 'I1' but required in type 'C3'.
7-
tests/cases/compiler/arrayAssignmentTest2.ts(51,1): error TS2740: Type '() => C1' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
8-
tests/cases/compiler/arrayAssignmentTest2.ts(52,1): error TS2740: Type '() => any' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
7+
tests/cases/compiler/arrayAssignmentTest2.ts(51,1): error TS2322: Type '() => C1' is not assignable to type 'any[]'.
8+
tests/cases/compiler/arrayAssignmentTest2.ts(52,1): error TS2322: Type '() => any' is not assignable to type 'any[]'.
99
tests/cases/compiler/arrayAssignmentTest2.ts(53,1): error TS2740: Type '{ one: number; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
1010
tests/cases/compiler/arrayAssignmentTest2.ts(55,1): error TS2740: Type 'C1' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
1111
tests/cases/compiler/arrayAssignmentTest2.ts(56,1): error TS2740: Type 'C2' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
@@ -78,10 +78,10 @@ tests/cases/compiler/arrayAssignmentTest2.ts(58,1): error TS2740: Type 'I1' is m
7878

7979
arr_any = f1; // should be an error - is
8080
~~~~~~~
81-
!!! error TS2740: Type '() => C1' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
81+
!!! error TS2322: Type '() => C1' is not assignable to type 'any[]'.
8282
arr_any = function () { return null;} // should be an error - is
8383
~~~~~~~
84-
!!! error TS2740: Type '() => any' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
84+
!!! error TS2322: Type '() => any' is not assignable to type 'any[]'.
8585
arr_any = o1; // should be an error - is
8686
~~~~~~~
8787
!!! error TS2740: Type '{ one: number; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.

tests/baselines/reference/arrayAssignmentTest4.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/compiler/arrayAssignmentTest4.ts(22,1): error TS2740: Type '() => any' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
1+
tests/cases/compiler/arrayAssignmentTest4.ts(22,1): error TS2322: Type '() => any' is not assignable to type 'any[]'.
22
tests/cases/compiler/arrayAssignmentTest4.ts(23,1): error TS2740: Type 'C3' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
33

44

@@ -26,7 +26,7 @@ tests/cases/compiler/arrayAssignmentTest4.ts(23,1): error TS2740: Type 'C3' is m
2626

2727
arr_any = function () { return null;} // should be an error - is
2828
~~~~~~~
29-
!!! error TS2740: Type '() => any' is missing the following properties from type 'any[]': pop, push, concat, join, and 15 more.
29+
!!! error TS2322: Type '() => any' is not assignable to type 'any[]'.
3030
arr_any = c3; // should be an error - is
3131
~~~~~~~
3232
!!! error TS2740: Type 'C3' is missing the following properties from type 'any[]': length, pop, push, concat, and 16 more.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
tests/cases/compiler/assignLambdaToNominalSubtypeOfFunction.ts(7,4): error TS2345: Argument of type '(a: any, b: any) => boolean' is not assignable to parameter of type 'IResultCallback'.
2-
Property 'x' is missing in type '(a: any, b: any) => boolean' but required in type 'IResultCallback'.
32
tests/cases/compiler/assignLambdaToNominalSubtypeOfFunction.ts(8,4): error TS2345: Argument of type '(a: any, b: any) => boolean' is not assignable to parameter of type 'IResultCallback'.
4-
Property 'x' is missing in type '(a: any, b: any) => boolean' but required in type 'IResultCallback'.
53

64

75
==== tests/cases/compiler/assignLambdaToNominalSubtypeOfFunction.ts (2 errors) ====
@@ -14,11 +12,7 @@ tests/cases/compiler/assignLambdaToNominalSubtypeOfFunction.ts(8,4): error TS234
1412
fn((a, b) => true);
1513
~~~~~~~~~~~~~~
1614
!!! error TS2345: Argument of type '(a: any, b: any) => boolean' is not assignable to parameter of type 'IResultCallback'.
17-
!!! error TS2345: Property 'x' is missing in type '(a: any, b: any) => boolean' but required in type 'IResultCallback'.
18-
!!! related TS2728 tests/cases/compiler/assignLambdaToNominalSubtypeOfFunction.ts:2:5: 'x' is declared here.
1915
fn(function (a, b) { return true; })
2016
~~~~~~~~
2117
!!! error TS2345: Argument of type '(a: any, b: any) => boolean' is not assignable to parameter of type 'IResultCallback'.
22-
!!! error TS2345: Property 'x' is missing in type '(a: any, b: any) => boolean' but required in type 'IResultCallback'.
23-
!!! related TS2728 tests/cases/compiler/assignLambdaToNominalSubtypeOfFunction.ts:2:5: 'x' is declared here.
2418

tests/baselines/reference/assignmentCompatWithCallSignatures2.errors.txt

+16-24
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(31,1): error TS2741: Property 'f' is missing in type '() => number' but required in type 'T'.
2-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(32,1): error TS2741: Property 'f' is missing in type '(x: number) => string' but required in type 'T'.
3-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(33,1): error TS2741: Property 'f' is missing in type '() => number' but required in type '{ f(x: number): void; }'.
4-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(34,1): error TS2741: Property 'f' is missing in type '(x: number) => string' but required in type '{ f(x: number): void; }'.
1+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(31,1): error TS2322: Type '() => number' is not assignable to type 'T'.
2+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(32,1): error TS2322: Type '(x: number) => string' is not assignable to type 'T'.
3+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(33,1): error TS2322: Type '() => number' is not assignable to type '{ f(x: number): void; }'.
4+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(34,1): error TS2322: Type '(x: number) => string' is not assignable to type '{ f(x: number): void; }'.
55
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(42,1): error TS2322: Type 'S2' is not assignable to type 'T'.
66
Types of property 'f' are incompatible.
77
Type '(x: string) => void' is not assignable to type '(x: number) => void'.
@@ -12,8 +12,8 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
1212
Type '(x: string) => void' is not assignable to type '(x: number) => void'.
1313
Types of parameters 'x' and 'x' are incompatible.
1414
Type 'number' is not assignable to type 'string'.
15-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(44,1): error TS2741: Property 'f' is missing in type '(x: string) => number' but required in type 'T'.
16-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(45,1): error TS2741: Property 'f' is missing in type '(x: string) => string' but required in type 'T'.
15+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(44,1): error TS2322: Type '(x: string) => number' is not assignable to type 'T'.
16+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(45,1): error TS2322: Type '(x: string) => string' is not assignable to type 'T'.
1717
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(46,1): error TS2322: Type 'S2' is not assignable to type '{ f(x: number): void; }'.
1818
Types of property 'f' are incompatible.
1919
Type '(x: string) => void' is not assignable to type '(x: number) => void'.
@@ -24,8 +24,8 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
2424
Type '(x: string) => void' is not assignable to type '(x: number) => void'.
2525
Types of parameters 'x' and 'x' are incompatible.
2626
Type 'number' is not assignable to type 'string'.
27-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(48,1): error TS2741: Property 'f' is missing in type '(x: string) => number' but required in type '{ f(x: number): void; }'.
28-
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(49,1): error TS2741: Property 'f' is missing in type '(x: string) => string' but required in type '{ f(x: number): void; }'.
27+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(48,1): error TS2322: Type '(x: string) => number' is not assignable to type '{ f(x: number): void; }'.
28+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts(49,1): error TS2322: Type '(x: string) => string' is not assignable to type '{ f(x: number): void; }'.
2929

3030

3131
==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts (12 errors) ====
@@ -61,20 +61,16 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
6161
// errors
6262
t = () => 1;
6363
~
64-
!!! error TS2741: Property 'f' is missing in type '() => number' but required in type 'T'.
65-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:4:5: 'f' is declared here.
64+
!!! error TS2322: Type '() => number' is not assignable to type 'T'.
6665
t = function (x: number) { return ''; }
6766
~
68-
!!! error TS2741: Property 'f' is missing in type '(x: number) => string' but required in type 'T'.
69-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:4:5: 'f' is declared here.
67+
!!! error TS2322: Type '(x: number) => string' is not assignable to type 'T'.
7068
a = () => 1;
7169
~
72-
!!! error TS2741: Property 'f' is missing in type '() => number' but required in type '{ f(x: number): void; }'.
73-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:7:10: 'f' is declared here.
70+
!!! error TS2322: Type '() => number' is not assignable to type '{ f(x: number): void; }'.
7471
a = function (x: number) { return ''; }
7572
~
76-
!!! error TS2741: Property 'f' is missing in type '(x: number) => string' but required in type '{ f(x: number): void; }'.
77-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:7:10: 'f' is declared here.
73+
!!! error TS2322: Type '(x: number) => string' is not assignable to type '{ f(x: number): void; }'.
7874

7975
interface S2 {
8076
f(x: string): void;
@@ -98,12 +94,10 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
9894
!!! error TS2322: Type 'number' is not assignable to type 'string'.
9995
t = (x: string) => 1;
10096
~
101-
!!! error TS2741: Property 'f' is missing in type '(x: string) => number' but required in type 'T'.
102-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:4:5: 'f' is declared here.
97+
!!! error TS2322: Type '(x: string) => number' is not assignable to type 'T'.
10398
t = function (x: string) { return ''; }
10499
~
105-
!!! error TS2741: Property 'f' is missing in type '(x: string) => string' but required in type 'T'.
106-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:4:5: 'f' is declared here.
100+
!!! error TS2322: Type '(x: string) => string' is not assignable to type 'T'.
107101
a = s2;
108102
~
109103
!!! error TS2322: Type 'S2' is not assignable to type '{ f(x: number): void; }'.
@@ -120,10 +114,8 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme
120114
!!! error TS2322: Type 'number' is not assignable to type 'string'.
121115
a = (x: string) => 1;
122116
~
123-
!!! error TS2741: Property 'f' is missing in type '(x: string) => number' but required in type '{ f(x: number): void; }'.
124-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:7:10: 'f' is declared here.
117+
!!! error TS2322: Type '(x: string) => number' is not assignable to type '{ f(x: number): void; }'.
125118
a = function (x: string) { return ''; }
126119
~
127-
!!! error TS2741: Property 'f' is missing in type '(x: string) => string' but required in type '{ f(x: number): void; }'.
128-
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithCallSignatures2.ts:7:10: 'f' is declared here.
120+
!!! error TS2322: Type '(x: string) => string' is not assignable to type '{ f(x: number): void; }'.
129121

0 commit comments

Comments
 (0)