Show elaboration for property not existing in union

Fixes #10256. Accessing a non-existant property on union types should
now show an elaboration in the error message specifying the first
constituent type that lacks the property.
This commit is contained in:
Omer Sheikh 2016-08-28 12:29:05 +05:00
parent 598ca48c94
commit 59d027b49b
6 changed files with 43 additions and 3 deletions

View File

@ -10773,7 +10773,7 @@ namespace ts {
const prop = getPropertyOfType(apparentType, right.text);
if (!prop) {
if (right.text && !checkAndReportErrorForExtendingInterface(node)) {
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type.flags & TypeFlags.ThisType ? apparentType : type));
reportNonexistantProperty(right, type.flags & TypeFlags.ThisType ? apparentType : type);
}
return unknownType;
}
@ -10810,6 +10810,20 @@ namespace ts {
return propType;
}
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined);
function reportNonexistantProperty(propNode: Identifier, containingType: Type) {
let errorInfo: DiagnosticMessageChain;
if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Enum)) {
for (const subtype of (containingType as UnionType).types) {
if (!getPropertyOfType(subtype, propNode.text)) {
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype));
break;
}
}
}
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo));
}
}
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {

View File

@ -1,8 +1,10 @@
tests/cases/compiler/propertyAccess3.ts(2,5): error TS2339: Property 'toBAZ' does not exist on type 'boolean'.
Property 'toBAZ' does not exist on type 'true'.
==== tests/cases/compiler/propertyAccess3.ts (1 errors) ====
var foo: boolean;
foo.toBAZ();
~~~~~
!!! error TS2339: Property 'toBAZ' does not exist on type 'boolean'.
!!! error TS2339: Property 'toBAZ' does not exist on type 'boolean'.
!!! error TS2339: Property 'toBAZ' does not exist on type 'true'.

View File

@ -1,6 +1,7 @@
tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(11,7): error TS2339: Property 'p' does not exist on type 'string'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(18,7): error TS2339: Property 'p' does not exist on type 'number'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(25,7): error TS2339: Property 'p' does not exist on type 'boolean'.
Property 'p' does not exist on type 'true'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts (3 errors) ====
@ -35,6 +36,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts(25,7): error
x.p; // Error, type any narrowed by primitive type check
~
!!! error TS2339: Property 'p' does not exist on type 'boolean'.
!!! error TS2339: Property 'p' does not exist on type 'true'.
}
else {
x.p; // No error, type unaffected in this branch

View File

@ -5,14 +5,20 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(41,10): error TS2339: Property 'bar' does not exist on type 'B<any>'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(66,10): error TS2339: Property 'bar2' does not exist on type 'C1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(72,10): error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
Property 'bar1' does not exist on type 'C2'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(73,10): error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
Property 'bar2' does not exist on type 'C1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(85,10): error TS2339: Property 'bar' does not exist on type 'D'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(91,10): error TS2339: Property 'bar' does not exist on type 'D'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(112,10): error TS2339: Property 'bar2' does not exist on type 'E1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(118,11): error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
Property 'bar1' does not exist on type 'E2'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(119,11): error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
Property 'bar2' does not exist on type 'E1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(134,11): error TS2339: Property 'foo' does not exist on type 'string | F'.
Property 'foo' does not exist on type 'string'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(135,11): error TS2339: Property 'bar' does not exist on type 'string | F'.
Property 'bar' does not exist on type 'string'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(160,11): error TS2339: Property 'foo2' does not exist on type 'G1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(166,11): error TS2339: Property 'foo2' does not exist on type 'G1'.
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(182,11): error TS2339: Property 'bar' does not exist on type 'H'.
@ -107,9 +113,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
obj6.bar1;
~~~~
!!! error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
!!! error TS2339: Property 'bar1' does not exist on type 'C2'.
obj6.bar2;
~~~~
!!! error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
!!! error TS2339: Property 'bar2' does not exist on type 'C1'.
}
// with object type literal
@ -163,9 +171,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
obj10.bar1;
~~~~
!!! error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
!!! error TS2339: Property 'bar1' does not exist on type 'E2'.
obj10.bar2;
~~~~
!!! error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
!!! error TS2339: Property 'bar2' does not exist on type 'E1'.
}
// a construct signature that returns any
@ -183,9 +193,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
obj11.foo;
~~~
!!! error TS2339: Property 'foo' does not exist on type 'string | F'.
!!! error TS2339: Property 'foo' does not exist on type 'string'.
obj11.bar;
~~~
!!! error TS2339: Property 'bar' does not exist on type 'string | F'.
!!! error TS2339: Property 'bar' does not exist on type 'string'.
}
var obj12: any;

View File

@ -1,8 +1,12 @@
tests/cases/conformance/types/union/unionTypeMembers.ts(44,1): error TS2349: Cannot invoke an expression whose type lacks a call signature.
tests/cases/conformance/types/union/unionTypeMembers.ts(51,3): error TS2339: Property 'propertyOnlyInI1' does not exist on type 'I1<number> | I2<number>'.
Property 'propertyOnlyInI1' does not exist on type 'I2<number>'.
tests/cases/conformance/types/union/unionTypeMembers.ts(52,3): error TS2339: Property 'propertyOnlyInI2' does not exist on type 'I1<number> | I2<number>'.
Property 'propertyOnlyInI2' does not exist on type 'I1<number>'.
tests/cases/conformance/types/union/unionTypeMembers.ts(53,3): error TS2339: Property 'methodOnlyInI1' does not exist on type 'I1<number> | I2<number>'.
Property 'methodOnlyInI1' does not exist on type 'I2<number>'.
tests/cases/conformance/types/union/unionTypeMembers.ts(54,3): error TS2339: Property 'methodOnlyInI2' does not exist on type 'I1<number> | I2<number>'.
Property 'methodOnlyInI2' does not exist on type 'I1<number>'.
==== tests/cases/conformance/types/union/unionTypeMembers.ts (5 errors) ====
@ -61,12 +65,16 @@ tests/cases/conformance/types/union/unionTypeMembers.ts(54,3): error TS2339: Pro
x.propertyOnlyInI1; // error
~~~~~~~~~~~~~~~~
!!! error TS2339: Property 'propertyOnlyInI1' does not exist on type 'I1<number> | I2<number>'.
!!! error TS2339: Property 'propertyOnlyInI1' does not exist on type 'I2<number>'.
x.propertyOnlyInI2; // error
~~~~~~~~~~~~~~~~
!!! error TS2339: Property 'propertyOnlyInI2' does not exist on type 'I1<number> | I2<number>'.
!!! error TS2339: Property 'propertyOnlyInI2' does not exist on type 'I1<number>'.
x.methodOnlyInI1("hello"); // error
~~~~~~~~~~~~~~
!!! error TS2339: Property 'methodOnlyInI1' does not exist on type 'I1<number> | I2<number>'.
!!! error TS2339: Property 'methodOnlyInI1' does not exist on type 'I2<number>'.
x.methodOnlyInI2(10); // error
~~~~~~~~~~~~~~
!!! error TS2339: Property 'methodOnlyInI2' does not exist on type 'I1<number> | I2<number>'.
!!! error TS2339: Property 'methodOnlyInI2' does not exist on type 'I1<number> | I2<number>'.
!!! error TS2339: Property 'methodOnlyInI2' does not exist on type 'I1<number>'.

View File

@ -3,6 +3,7 @@ tests/cases/conformance/types/union/unionTypeReadonly.ts(19,1): error TS2450: Le
tests/cases/conformance/types/union/unionTypeReadonly.ts(21,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
tests/cases/conformance/types/union/unionTypeReadonly.ts(23,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
tests/cases/conformance/types/union/unionTypeReadonly.ts(25,15): error TS2339: Property 'value' does not exist on type 'Base | DifferentName'.
Property 'value' does not exist on type 'DifferentName'.
==== tests/cases/conformance/types/union/unionTypeReadonly.ts (5 errors) ====
@ -41,5 +42,6 @@ tests/cases/conformance/types/union/unionTypeReadonly.ts(25,15): error TS2339: P
differentName.value = 12; // error, property 'value' doesn't exist
~~~~~
!!! error TS2339: Property 'value' does not exist on type 'Base | DifferentName'.
!!! error TS2339: Property 'value' does not exist on type 'DifferentName'.