mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-16 05:58:32 -06:00
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:
parent
598ca48c94
commit
59d027b49b
@ -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 {
|
||||
|
||||
@ -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'.
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>'.
|
||||
@ -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'.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user