Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5d2055b

Browse files
committedApr 2, 2018
Fix issue microsoft#22923
1 parent 9b558f9 commit 5d2055b

17 files changed

+281
-1
lines changed
 

‎src/compiler/checker.ts

+14
Original file line numberDiff line numberDiff line change
@@ -16406,9 +16406,15 @@ namespace ts {
1640616406
}
1640716407
}
1640816408
const suggestion = getSuggestionForNonexistentProperty(propNode, containingType);
16409+
const subtypeHavingProperty = typeHavingProperty(containingType, propNode.escapedText);
16410+
1640916411
if (suggestion !== undefined) {
1641016412
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
1641116413
}
16414+
else if (subtypeHavingProperty) {
16415+
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_forget_to_await_the_1_as_property_0_exists_on_awaited_2,
16416+
declarationNameToString(propNode), typeToString(containingType), typeToString(subtypeHavingProperty));
16417+
}
1641216418
else {
1641316419
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
1641416420
}
@@ -16420,6 +16426,14 @@ namespace ts {
1642016426
return suggestion && symbolName(suggestion);
1642116427
}
1642216428

16429+
function typeHavingProperty(type: Type, property: __String, errorNode?: Node): Type | undefined {
16430+
const types: Type[] = (type.flags & TypeFlags.UnionOrIntersection)
16431+
? (type as UnionOrIntersectionType).types : [type];
16432+
16433+
return find(types.map(t => getPromisedTypeOfPromise(t, errorNode)).filter(t => t !== undefined),
16434+
t => getPropertyOfType(t, property) !== undefined);
16435+
}
16436+
1642316437
function getSuggestionForNonexistentSymbol(location: Node, outerName: __String, meaning: SymbolFlags): string {
1642416438
Debug.assert(outerName !== undefined, "outername should always be defined");
1642516439
const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, (symbols, name, meaning) => {

‎src/compiler/diagnosticMessages.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -2000,7 +2000,10 @@
20002000
"category": "Error",
20012001
"code": 2569
20022002
},
2003-
2003+
"Property '{0}' does not exist on type '{1}'. Did you forget to await the '{1}' as property '{0}' exists on awaited '{2}'?": {
2004+
"category": "Error",
2005+
"code": 2570
2006+
},
20042007
"JSX element attributes type '{0}' may not be a union type.": {
20052008
"category": "Error",
20062009
"code": 2600
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
tests/cases/compiler/missingPropertyOfPromise.ts(2,7): error TS2570: Property 'toLowerCase' does not exist on type 'Promise<string>'. Did you forget to await the 'Promise<string>' as property 'toLowerCase' exists on awaited 'string'?
2+
3+
4+
==== tests/cases/compiler/missingPropertyOfPromise.ts (1 errors) ====
5+
function f(x: Promise<string>) {
6+
x.toLowerCase();
7+
~~~~~~~~~~~
8+
!!! error TS2570: Property 'toLowerCase' does not exist on type 'Promise<string>'. Did you forget to await the 'Promise<string>' as property 'toLowerCase' exists on awaited 'string'?
9+
}
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [missingPropertyOfPromise.ts]
2+
function f(x: Promise<string>) {
3+
x.toLowerCase();
4+
}
5+
6+
7+
//// [missingPropertyOfPromise.js]
8+
function f(x) {
9+
x.toLowerCase();
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/compiler/missingPropertyOfPromise.ts ===
2+
function f(x: Promise<string>) {
3+
>f : Symbol(f, Decl(missingPropertyOfPromise.ts, 0, 0))
4+
>x : Symbol(x, Decl(missingPropertyOfPromise.ts, 0, 11))
5+
>Promise : Symbol(Promise, Decl(lib.d.ts, --, --))
6+
7+
x.toLowerCase();
8+
>x : Symbol(x, Decl(missingPropertyOfPromise.ts, 0, 11))
9+
}
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/compiler/missingPropertyOfPromise.ts ===
2+
function f(x: Promise<string>) {
3+
>f : (x: Promise<string>) => void
4+
>x : Promise<string>
5+
>Promise : Promise<T>
6+
7+
x.toLowerCase();
8+
>x.toLowerCase() : any
9+
>x.toLowerCase : any
10+
>x : Promise<string>
11+
>toLowerCase : any
12+
}
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
tests/cases/compiler/missingPropertyOfPromiseIntersection.ts(10,7): error TS2570: Property 'method' does not exist on type 'Promise<Foo> & Bar'. Did you forget to await the 'Promise<Foo> & Bar' as property 'method' exists on awaited 'Foo'?
2+
3+
4+
==== tests/cases/compiler/missingPropertyOfPromiseIntersection.ts (1 errors) ====
5+
interface Foo {
6+
method();
7+
}
8+
9+
interface Bar {
10+
somethingElse();
11+
}
12+
13+
function f(x: Promise<Foo> & Bar) {
14+
x.method();
15+
~~~~~~
16+
!!! error TS2570: Property 'method' does not exist on type 'Promise<Foo> & Bar'. Did you forget to await the 'Promise<Foo> & Bar' as property 'method' exists on awaited 'Foo'?
17+
}
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [missingPropertyOfPromiseIntersection.ts]
2+
interface Foo {
3+
method();
4+
}
5+
6+
interface Bar {
7+
somethingElse();
8+
}
9+
10+
function f(x: Promise<Foo> & Bar) {
11+
x.method();
12+
}
13+
14+
15+
//// [missingPropertyOfPromiseIntersection.js]
16+
function f(x) {
17+
x.method();
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/compiler/missingPropertyOfPromiseIntersection.ts ===
2+
interface Foo {
3+
>Foo : Symbol(Foo, Decl(missingPropertyOfPromiseIntersection.ts, 0, 0))
4+
5+
method();
6+
>method : Symbol(Foo.method, Decl(missingPropertyOfPromiseIntersection.ts, 0, 15))
7+
}
8+
9+
interface Bar {
10+
>Bar : Symbol(Bar, Decl(missingPropertyOfPromiseIntersection.ts, 2, 1))
11+
12+
somethingElse();
13+
>somethingElse : Symbol(Bar.somethingElse, Decl(missingPropertyOfPromiseIntersection.ts, 4, 15))
14+
}
15+
16+
function f(x: Promise<Foo> & Bar) {
17+
>f : Symbol(f, Decl(missingPropertyOfPromiseIntersection.ts, 6, 1))
18+
>x : Symbol(x, Decl(missingPropertyOfPromiseIntersection.ts, 8, 11))
19+
>Promise : Symbol(Promise, Decl(lib.d.ts, --, --))
20+
>Foo : Symbol(Foo, Decl(missingPropertyOfPromiseIntersection.ts, 0, 0))
21+
>Bar : Symbol(Bar, Decl(missingPropertyOfPromiseIntersection.ts, 2, 1))
22+
23+
x.method();
24+
>x : Symbol(x, Decl(missingPropertyOfPromiseIntersection.ts, 8, 11))
25+
}
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/compiler/missingPropertyOfPromiseIntersection.ts ===
2+
interface Foo {
3+
>Foo : Foo
4+
5+
method();
6+
>method : () => any
7+
}
8+
9+
interface Bar {
10+
>Bar : Bar
11+
12+
somethingElse();
13+
>somethingElse : () => any
14+
}
15+
16+
function f(x: Promise<Foo> & Bar) {
17+
>f : (x: Promise<Foo> & Bar) => void
18+
>x : Promise<Foo> & Bar
19+
>Promise : Promise<T>
20+
>Foo : Foo
21+
>Bar : Bar
22+
23+
x.method();
24+
>x.method() : any
25+
>x.method : any
26+
>x : Promise<Foo> & Bar
27+
>method : any
28+
}
29+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
tests/cases/compiler/missingPropertyOfPromiseUnion.ts(11,7): error TS2570: Property 'method' does not exist on type 'Promise<Foo> | Promise<Bar>'. Did you forget to await the 'Promise<Foo> | Promise<Bar>' as property 'method' exists on awaited 'Foo'?
2+
Property 'method' does not exist on type 'Promise<Foo>'.
3+
4+
5+
==== tests/cases/compiler/missingPropertyOfPromiseUnion.ts (1 errors) ====
6+
interface Foo {
7+
method();
8+
}
9+
10+
interface Bar {
11+
method();
12+
somethingElse();
13+
}
14+
15+
function f(x: Promise<Foo> | Promise<Bar>) {
16+
x.method();
17+
~~~~~~
18+
!!! error TS2570: Property 'method' does not exist on type 'Promise<Foo> | Promise<Bar>'. Did you forget to await the 'Promise<Foo> | Promise<Bar>' as property 'method' exists on awaited 'Foo'?
19+
!!! error TS2570: Property 'method' does not exist on type 'Promise<Foo>'.
20+
}
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//// [missingPropertyOfPromiseUnion.ts]
2+
interface Foo {
3+
method();
4+
}
5+
6+
interface Bar {
7+
method();
8+
somethingElse();
9+
}
10+
11+
function f(x: Promise<Foo> | Promise<Bar>) {
12+
x.method();
13+
}
14+
15+
16+
//// [missingPropertyOfPromiseUnion.js]
17+
function f(x) {
18+
x.method();
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
=== tests/cases/compiler/missingPropertyOfPromiseUnion.ts ===
2+
interface Foo {
3+
>Foo : Symbol(Foo, Decl(missingPropertyOfPromiseUnion.ts, 0, 0))
4+
5+
method();
6+
>method : Symbol(Foo.method, Decl(missingPropertyOfPromiseUnion.ts, 0, 15))
7+
}
8+
9+
interface Bar {
10+
>Bar : Symbol(Bar, Decl(missingPropertyOfPromiseUnion.ts, 2, 1))
11+
12+
method();
13+
>method : Symbol(Bar.method, Decl(missingPropertyOfPromiseUnion.ts, 4, 15))
14+
15+
somethingElse();
16+
>somethingElse : Symbol(Bar.somethingElse, Decl(missingPropertyOfPromiseUnion.ts, 5, 13))
17+
}
18+
19+
function f(x: Promise<Foo> | Promise<Bar>) {
20+
>f : Symbol(f, Decl(missingPropertyOfPromiseUnion.ts, 7, 1))
21+
>x : Symbol(x, Decl(missingPropertyOfPromiseUnion.ts, 9, 11))
22+
>Promise : Symbol(Promise, Decl(lib.d.ts, --, --))
23+
>Foo : Symbol(Foo, Decl(missingPropertyOfPromiseUnion.ts, 0, 0))
24+
>Promise : Symbol(Promise, Decl(lib.d.ts, --, --))
25+
>Bar : Symbol(Bar, Decl(missingPropertyOfPromiseUnion.ts, 2, 1))
26+
27+
x.method();
28+
>x : Symbol(x, Decl(missingPropertyOfPromiseUnion.ts, 9, 11))
29+
}
30+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/missingPropertyOfPromiseUnion.ts ===
2+
interface Foo {
3+
>Foo : Foo
4+
5+
method();
6+
>method : () => any
7+
}
8+
9+
interface Bar {
10+
>Bar : Bar
11+
12+
method();
13+
>method : () => any
14+
15+
somethingElse();
16+
>somethingElse : () => any
17+
}
18+
19+
function f(x: Promise<Foo> | Promise<Bar>) {
20+
>f : (x: Promise<Foo> | Promise<Bar>) => void
21+
>x : Promise<Foo> | Promise<Bar>
22+
>Promise : Promise<T>
23+
>Foo : Foo
24+
>Promise : Promise<T>
25+
>Bar : Bar
26+
27+
x.method();
28+
>x.method() : any
29+
>x.method : any
30+
>x : Promise<Foo> | Promise<Bar>
31+
>method : any
32+
}
33+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function f(x: Promise<string>) {
2+
x.toLowerCase();
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
interface Foo {
2+
method();
3+
}
4+
5+
interface Bar {
6+
somethingElse();
7+
}
8+
9+
function f(x: Promise<Foo> & Bar) {
10+
x.method();
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
interface Foo {
2+
method();
3+
}
4+
5+
interface Bar {
6+
method();
7+
somethingElse();
8+
}
9+
10+
function f(x: Promise<Foo> | Promise<Bar>) {
11+
x.method();
12+
}

0 commit comments

Comments
 (0)
Please sign in to comment.