Skip to content

Commit a2c66c3

Browse files
authored
Merge pull request #17660 from Microsoft/weak-type-errors-on-signature-only-types
Weak type errors on signature-only types
2 parents 85f5909 + 7ff1d8e commit a2c66c3

File tree

5 files changed

+51
-20
lines changed

5 files changed

+51
-20
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8941,11 +8941,21 @@ namespace ts {
89418941
!(target.flags & TypeFlags.Union) &&
89428942
!isIntersectionConstituent &&
89438943
source !== globalObjectType &&
8944-
getPropertiesOfType(source).length > 0 &&
8944+
(getPropertiesOfType(source).length > 0 ||
8945+
getSignaturesOfType(source, SignatureKind.Call).length > 0 ||
8946+
getSignaturesOfType(source, SignatureKind.Construct).length > 0) &&
89458947
isWeakType(target) &&
89468948
!hasCommonProperties(source, target)) {
89478949
if (reportErrors) {
8948-
reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target));
8950+
const calls = getSignaturesOfType(source, SignatureKind.Call);
8951+
const constructs = getSignaturesOfType(source, SignatureKind.Construct);
8952+
if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, /*reportErrors*/ false) ||
8953+
constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, /*reportErrors*/ false)) {
8954+
reportError(Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, typeToString(source), typeToString(target));
8955+
}
8956+
else {
8957+
reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target));
8958+
}
89498959
}
89508960
return Ternary.False;
89518961
}

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,10 @@
19081908
"category": "Error",
19091909
"code": 2559
19101910
},
1911+
"Value of type '{0}' has no properties in common with type '{1}'. Did you mean to call it?": {
1912+
"category": "Error",
1913+
"code": 2560
1914+
},
19111915
"JSX element attributes type '{0}' may not be a union type.": {
19121916
"category": "Error",
19131917
"code": 2600

tests/baselines/reference/weakType.errors.txt

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
tests/cases/compiler/weakType.ts(16,13): error TS2559: Type '12' has no properties in common with type 'Settings'.
2-
tests/cases/compiler/weakType.ts(17,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'.
3-
tests/cases/compiler/weakType.ts(18,13): error TS2559: Type 'false' has no properties in common with type 'Settings'.
4-
tests/cases/compiler/weakType.ts(35,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'.
5-
tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
1+
tests/cases/compiler/weakType.ts(15,13): error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it?
2+
tests/cases/compiler/weakType.ts(16,13): error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it?
3+
tests/cases/compiler/weakType.ts(17,13): error TS2560: Value of type 'CtorOnly' has no properties in common with type 'Settings'. Did you mean to call it?
4+
tests/cases/compiler/weakType.ts(18,13): error TS2559: Type '12' has no properties in common with type 'Settings'.
5+
tests/cases/compiler/weakType.ts(19,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'.
6+
tests/cases/compiler/weakType.ts(20,13): error TS2559: Type 'false' has no properties in common with type 'Settings'.
7+
tests/cases/compiler/weakType.ts(37,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'.
8+
tests/cases/compiler/weakType.ts(62,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
69
Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'.
710
Types of property 'properties' are incompatible.
811
Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.
912

1013

11-
==== tests/cases/compiler/weakType.ts (5 errors) ====
14+
==== tests/cases/compiler/weakType.ts (8 errors) ====
1215
interface Settings {
1316
timeout?: number;
1417
onError?(): void;
@@ -17,13 +20,21 @@ tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wron
1720
function getDefaultSettings() {
1821
return { timeout: 1000 };
1922
}
23+
interface CtorOnly {
24+
new(s: string): { timeout: 1000 }
25+
}
2026

2127
function doSomething(settings: Settings) { /* ... */ }
2228
// forgot to call `getDefaultSettings`
23-
// but it is not caught because we don't check for call signatures
2429
doSomething(getDefaultSettings);
25-
// same for arrow expressions:
26-
doSomething(() => { });
30+
~~~~~~~~~~~~~~~~~~
31+
!!! error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it?
32+
doSomething(() => ({ timeout: 1000 }));
33+
~~~~~~~~~~~~~~~~~~~~~~~~~
34+
!!! error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it?
35+
doSomething(null as CtorOnly);
36+
~~~~~~~~~~~~~~~~
37+
!!! error TS2560: Value of type 'CtorOnly' has no properties in common with type 'Settings'. Did you mean to call it?
2738
doSomething(12);
2839
~~
2940
!!! error TS2559: Type '12' has no properties in common with type 'Settings'.
@@ -82,4 +93,5 @@ tests/cases/compiler/weakType.ts(60,5): error TS2322: Type '{ properties: { wron
8293
!!! error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'.
8394
!!! error TS2322: Types of property 'properties' are incompatible.
8495
!!! error TS2322: Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.
96+
8597

tests/baselines/reference/weakType.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ interface Settings {
77
function getDefaultSettings() {
88
return { timeout: 1000 };
99
}
10+
interface CtorOnly {
11+
new(s: string): { timeout: 1000 }
12+
}
1013

1114
function doSomething(settings: Settings) { /* ... */ }
1215
// forgot to call `getDefaultSettings`
13-
// but it is not caught because we don't check for call signatures
1416
doSomething(getDefaultSettings);
15-
// same for arrow expressions:
16-
doSomething(() => { });
17+
doSomething(() => ({ timeout: 1000 }));
18+
doSomething(null as CtorOnly);
1719
doSomething(12);
1820
doSomething('completely wrong');
1921
doSomething(false);
@@ -59,6 +61,7 @@ declare let unknown: {
5961
}
6062
}
6163
let weak: Weak & Spoiler = unknown
64+
6265

6366

6467
//// [weakType.js]
@@ -67,10 +70,9 @@ function getDefaultSettings() {
6770
}
6871
function doSomething(settings) { }
6972
// forgot to call `getDefaultSettings`
70-
// but it is not caught because we don't check for call signatures
7173
doSomething(getDefaultSettings);
72-
// same for arrow expressions:
73-
doSomething(function () { });
74+
doSomething(function () { return ({ timeout: 1000 }); });
75+
doSomething(null);
7476
doSomething(12);
7577
doSomething('completely wrong');
7678
doSomething(false);

tests/cases/compiler/weakType.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ interface Settings {
66
function getDefaultSettings() {
77
return { timeout: 1000 };
88
}
9+
interface CtorOnly {
10+
new(s: string): { timeout: 1000 }
11+
}
912

1013
function doSomething(settings: Settings) { /* ... */ }
1114
// forgot to call `getDefaultSettings`
12-
// but it is not caught because we don't check for call signatures
1315
doSomething(getDefaultSettings);
14-
// same for arrow expressions:
15-
doSomething(() => { });
16+
doSomething(() => ({ timeout: 1000 }));
17+
doSomething(null as CtorOnly);
1618
doSomething(12);
1719
doSomething('completely wrong');
1820
doSomething(false);
@@ -58,3 +60,4 @@ declare let unknown: {
5860
}
5961
}
6062
let weak: Weak & Spoiler = unknown
63+

0 commit comments

Comments
 (0)