Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip parent error when reporting excess property checks #55152

19 changes: 16 additions & 3 deletions src/compiler/checker.ts
Expand Up @@ -20369,6 +20369,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
let expandingFlags = ExpandingFlags.None;
let overflow = false;
let overrideNextErrorInfo = 0; // How many `reportRelationError` calls should be skipped in the elaboration pyramid
let skipParentCounter = 0; // How many errors should be skipped 'above' in the elaboration pyramid
let lastSkippedInfo: [Type, Type] | undefined;
let incompatibleStack: DiagnosticAndArguments[] | undefined;

Expand Down Expand Up @@ -20430,6 +20431,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
lastSkippedInfo = saved.lastSkippedInfo;
incompatibleStack = saved.incompatibleStack;
overrideNextErrorInfo = saved.overrideNextErrorInfo;
skipParentCounter = saved.skipParentCounter;
relatedInfo = saved.relatedInfo;
}

Expand All @@ -20439,6 +20441,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
lastSkippedInfo,
incompatibleStack: incompatibleStack?.slice(),
overrideNextErrorInfo,
skipParentCounter,
relatedInfo: relatedInfo?.slice() as [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined,
};
}
Expand Down Expand Up @@ -20561,7 +20564,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
Debug.assert(!!errorNode);
if (incompatibleStack) reportIncompatibleStack();
if (message.elidedInCompatabilityPyramid) return;
errorInfo = chainDiagnosticMessages(errorInfo, message, ...args);
if (skipParentCounter === 0) {
errorInfo = chainDiagnosticMessages(errorInfo, message, ...args);
}
else {
skipParentCounter--;
}
}

function reportParentSkippedError(message: DiagnosticMessage, ...args: DiagnosticArguments): void {
reportError(message, ...args);
skipParentCounter++;
}

function associateRelatedInfo(info: DiagnosticRelatedInformation) {
Expand Down Expand Up @@ -20958,11 +20971,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
if (suggestion !== undefined) {
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2,
reportParentSkippedError(Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2,
symbolToString(prop), typeToString(errorTarget), suggestion);
}
else {
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
reportParentSkippedError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
symbolToString(prop), typeToString(errorTarget));
}
}
Expand Down
6 changes: 2 additions & 4 deletions tests/baselines/reference/arrayCast.errors.txt
@@ -1,6 +1,5 @@
arrayCast.ts(3,23): error TS2352: Conversion of type '{ foo: string; }[]' to type '{ id: number; }[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type '{ foo: string; }' is not comparable to type '{ id: number; }'.
Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'.
Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'.


==== arrayCast.ts (1 errors) ====
Expand All @@ -9,8 +8,7 @@ arrayCast.ts(3,23): error TS2352: Conversion of type '{ foo: string; }[]' to typ
<{ id: number; }[]>[{ foo: "s" }];
~~~
!!! error TS2352: Conversion of type '{ foo: string; }[]' to type '{ id: number; }[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
!!! error TS2352: Type '{ foo: string; }' is not comparable to type '{ id: number; }'.
!!! error TS2352: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'.
!!! error TS2352: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'.
Comment on lines -13 to +11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error should never have been issued in the first place. It seems like a bug in our element-wise elaboration logic. Notice how in the following example one of these is has a missing property error and the other is an excess property error:

let okay = { foo: "" } as { id: 123 };
//         ~~~~~~~~~~~~~~~~~~~~~~~~~~
// Conversion of type '{ foo: string; }' to type '{ id: 123; }' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
//   Property 'id' is missing in type '{ foo: string; }' but required in type '{ id: 123; }'.

let waat = [{ foo: "" }] as { id: 123 }[];
//            ~~~
// Conversion of type '{ foo: string; }[]' to type '{ id: 123; }[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
//   Type '{ foo: string; }' is not comparable to type '{ id: 123; }'.
//     Object literal may only specify known properties, and 'foo' does not exist in type '{ id: 123; }'.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened up #55167

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wouldn’t ever expect an EPC error on a type assertion.


// Should succeed, as the {} element causes the type of the array to be {}[]
<{ id: number; }[]>[{ foo: "s" }, {}];
24 changes: 8 additions & 16 deletions tests/baselines/reference/arrayLiteralTypeInference.errors.txt
@@ -1,11 +1,7 @@
arrayLiteralTypeInference.ts(14,14): error TS2322: Type '{ id: number; trueness: false; }' is not assignable to type 'Action'.
Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
arrayLiteralTypeInference.ts(15,14): error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'Action'.
Object literal may only specify known properties, and 'name' does not exist in type 'Action'.
arrayLiteralTypeInference.ts(31,18): error TS2322: Type '{ id: number; trueness: false; }' is not assignable to type '{ id: number; }'.
Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
arrayLiteralTypeInference.ts(32,18): error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
arrayLiteralTypeInference.ts(14,14): error TS2353: Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
arrayLiteralTypeInference.ts(15,14): error TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'Action'.
arrayLiteralTypeInference.ts(31,18): error TS2353: Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
arrayLiteralTypeInference.ts(32,18): error TS2353: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.


==== arrayLiteralTypeInference.ts (4 errors) ====
Expand All @@ -24,12 +20,10 @@ arrayLiteralTypeInference.ts(32,18): error TS2322: Type '{ id: number; name: str
var x1: Action[] = [
{ id: 2, trueness: false },
~~~~~~~~
!!! error TS2322: Type '{ id: number; trueness: false; }' is not assignable to type 'Action'.
!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
!!! error TS2353: Object literal may only specify known properties, and 'trueness' does not exist in type 'Action'.
{ id: 3, name: "three" }
~~~~
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'Action'.
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type 'Action'.
!!! error TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'Action'.
]

var x2: Action[] = [
Expand All @@ -47,12 +41,10 @@ arrayLiteralTypeInference.ts(32,18): error TS2322: Type '{ id: number; name: str
[
{ id: 2, trueness: false },
~~~~~~~~
!!! error TS2322: Type '{ id: number; trueness: false; }' is not assignable to type '{ id: number; }'.
!!! error TS2322: Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'trueness' does not exist in type '{ id: number; }'.
{ id: 3, name: "three" }
~~~~
!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type '{ id: number; }'.
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'name' does not exist in type '{ id: number; }'.
]

var z2: { id: number }[] =
Expand Down
12 changes: 4 additions & 8 deletions tests/baselines/reference/arrayLiterals.errors.txt
@@ -1,7 +1,5 @@
arrayLiterals.ts(24,77): error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'.
Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
arrayLiterals.ts(24,101): error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'.
Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
arrayLiterals.ts(24,77): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
arrayLiterals.ts(24,101): error TS2353: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.


==== arrayLiterals.ts (2 errors) ====
Expand Down Expand Up @@ -30,12 +28,10 @@ arrayLiterals.ts(24,101): error TS2322: Type '{ a: string; b: number; c: number;
// Contextual type C with numeric index signature makes array literal of EveryType E of type BCT(E,C)[]
var context1: { [n: number]: { a: string; b: number; }; } = [{ a: '', b: 0, c: '' }, { a: "", b: 3, c: 0 }];
~
!!! error TS2322: Type '{ a: string; b: number; c: string; }' is not assignable to type '{ a: string; b: number; }'.
!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
!!! related TS6501 arrayLiterals.ts:24:17: The expected type comes from this index signature.
~
!!! error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type '{ a: string; b: number; }'.
!!! error TS2322: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'c' does not exist in type '{ a: string; b: number; }'.
!!! related TS6501 arrayLiterals.ts:24:17: The expected type comes from this index signature.
var context2 = [{ a: '', b: 0, c: '' }, { a: "", b: 3, c: 0 }];

Expand Down
18 changes: 6 additions & 12 deletions tests/baselines/reference/assignmentCompatBug2.errors.txt
@@ -1,9 +1,6 @@
assignmentCompatBug2.ts(1,27): error TS2322: Type '{ a: number; }' is not assignable to type '{ b: number; }'.
Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
assignmentCompatBug2.ts(3,8): error TS2322: Type '{ a: number; }' is not assignable to type '{ b: number; }'.
Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
assignmentCompatBug2.ts(5,13): error TS2322: Type '{ b: number; a: number; }' is not assignable to type '{ b: number; }'.
Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
assignmentCompatBug2.ts(1,27): error TS2353: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
assignmentCompatBug2.ts(3,8): error TS2353: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
assignmentCompatBug2.ts(5,13): error TS2353: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
assignmentCompatBug2.ts(15,1): error TS2741: Property 'm' is missing in type '{ f: (n: number) => number; g: (s: string) => number; }' but required in type '{ f(n: number): number; g(s: string): number; m: number; n?: number; k?(a: any): any; }'.
assignmentCompatBug2.ts(20,1): error TS2741: Property 'g' is missing in type '{ f: (n: number) => number; m: number; }' but required in type '{ f(n: number): number; g(s: string): number; m: number; n?: number; k?(a: any): any; }'.
assignmentCompatBug2.ts(33,1): error TS2741: Property 'm' is missing in type '{ f: (n: number) => number; g: (s: string) => number; n: number; k: (a: any) => any; }' but required in type '{ f(n: number): number; g(s: string): number; m: number; n?: number; k?(a: any): any; }'.
Expand All @@ -12,18 +9,15 @@ assignmentCompatBug2.ts(33,1): error TS2741: Property 'm' is missing in type '{
==== assignmentCompatBug2.ts (6 errors) ====
var b2: { b: number;} = { a: 0 }; // error
~
!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ b: number; }'.
!!! error TS2322: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.

b2 = { a: 0 }; // error
~
!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ b: number; }'.
!!! error TS2322: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.

b2 = {b: 0, a: 0 };
~
!!! error TS2322: Type '{ b: number; a: number; }' is not assignable to type '{ b: number; }'.
!!! error TS2322: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'a' does not exist in type '{ b: number; }'.

var b3: { f(n: number): number; g(s: string): number; m: number; n?: number; k?(a: any): any; };

Expand Down
6 changes: 2 additions & 4 deletions tests/baselines/reference/assignmentCompatBug5.errors.txt
@@ -1,5 +1,4 @@
assignmentCompatBug5.ts(2,8): error TS2345: Argument of type '{ b: number; }' is not assignable to parameter of type '{ a: number; }'.
Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'.
assignmentCompatBug5.ts(2,8): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'.
assignmentCompatBug5.ts(5,7): error TS2322: Type 'string' is not assignable to type 'number'.
assignmentCompatBug5.ts(5,12): error TS2322: Type 'string' is not assignable to type 'number'.
assignmentCompatBug5.ts(8,6): error TS2345: Argument of type '(s: string) => void' is not assignable to parameter of type '(n: number) => number'.
Expand All @@ -13,8 +12,7 @@ assignmentCompatBug5.ts(9,6): error TS2345: Argument of type '(n: number) => voi
function foo1(x: { a: number; }) { }
foo1({ b: 5 });
~
!!! error TS2345: Argument of type '{ b: number; }' is not assignable to parameter of type '{ a: number; }'.
!!! error TS2345: Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'.
!!! error TS2353: Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'.

function foo2(x: number[]) { }
foo2(["s", "t"]);
Expand Down
12 changes: 4 additions & 8 deletions tests/baselines/reference/checkJsdocSatisfiesTag1.errors.txt
@@ -1,9 +1,7 @@
/a.js(21,44): error TS1360: Type '{ a: number; b: number; }' does not satisfy the expected type 'T1'.
Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
/a.js(21,44): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
/a.js(22,17): error TS1360: Type '{}' does not satisfy the expected type 'T1'.
Property 'a' is missing in type '{}' but required in type 'T1'.
/a.js(31,49): error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'T4'.
Object literal may only specify known properties, and 'b' does not exist in type 'T4'.
/a.js(31,49): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T4'.


==== /a.js (3 errors) ====
Expand All @@ -29,8 +27,7 @@
const t1 = /** @satisfies {T1} */ ({ a: 1 });
const t2 = /** @satisfies {T1} */ ({ a: 1, b: 1 });
~
!!! error TS1360: Type '{ a: number; b: number; }' does not satisfy the expected type 'T1'.
!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
!!! error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
const t3 = /** @satisfies {T1} */ ({});
~~~~~~~~~
!!! error TS1360: Type '{}' does not satisfy the expected type 'T1'.
Expand All @@ -46,6 +43,5 @@
const t7 = /** @satisfies {T4} */ ({ a: 'test' });
const t8 = /** @satisfies {T4} */ ({ a: 'test', b: 'test' });
~
!!! error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'T4'.
!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'T4'.
!!! error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T4'.

6 changes: 2 additions & 4 deletions tests/baselines/reference/checkJsdocSatisfiesTag10.errors.txt
@@ -1,5 +1,4 @@
/a.js(6,5): error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial<Record<Keys, unknown>>'.
Object literal may only specify known properties, and 'x' does not exist in type 'Partial<Record<Keys, unknown>>'.
/a.js(6,5): error TS2353: Object literal may only specify known properties, and 'x' does not exist in type 'Partial<Record<Keys, unknown>>'.
/a.js(14,11): error TS2339: Property 'd' does not exist on type '{ a: number; b: string; x: number; }'.


Expand All @@ -11,8 +10,7 @@
b: "hello",
x: 8 // Should error, 'x' isn't in 'Keys'
~
!!! error TS1360: Type '{ a: number; b: string; x: number; }' does not satisfy the expected type 'Partial<Record<Keys, unknown>>'.
!!! error TS1360: Object literal may only specify known properties, and 'x' does not exist in type 'Partial<Record<Keys, unknown>>'.
!!! error TS2353: Object literal may only specify known properties, and 'x' does not exist in type 'Partial<Record<Keys, unknown>>'.
});

// Should be OK -- retain info that a is number and b is string
Expand Down
12 changes: 4 additions & 8 deletions tests/baselines/reference/checkJsdocSatisfiesTag12.errors.txt
@@ -1,7 +1,5 @@
/a.js(24,20): error TS1360: Type '{ a: number; b: number; }' does not satisfy the expected type 'T1'.
Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
/a.js(44,25): error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'T2'.
Object literal may only specify known properties, and 'b' does not exist in type 'T2'.
/a.js(24,20): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
/a.js(44,25): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T2'.
/a.js(51,6): error TS1360: Type 'number' does not satisfy the expected type 'string'.


Expand Down Expand Up @@ -31,8 +29,7 @@
*/
const t2 = { a: 1, b: 1 };
~
!!! error TS1360: Type '{ a: number; b: number; }' does not satisfy the expected type 'T1'.
!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
!!! error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.

/**
* @satisfies {T1}
Expand All @@ -54,8 +51,7 @@
*/
const t6 = { a: 'test', b: 'test' };
~
!!! error TS1360: Type '{ a: string; b: string; }' does not satisfy the expected type 'T2'.
!!! error TS1360: Object literal may only specify known properties, and 'b' does not exist in type 'T2'.
!!! error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T2'.

/**
* @satisfies {T3}
Expand Down