Skip to content

Commit d7390c0

Browse files
authored
Avoid elaborating on generic indexes (#28294)
1 parent 41d3f0a commit d7390c0

7 files changed

+158
-12
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10936,8 +10936,9 @@ namespace ts {
1093610936
let reportedError = false;
1093710937
for (let status = iterator.next(); !status.done; status = iterator.next()) {
1093810938
const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value;
10939-
const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType);
1094010939
const targetPropType = getIndexedAccessType(target, nameType, /*accessNode*/ undefined, errorType);
10940+
if (targetPropType === errorType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables
10941+
const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType);
1094110942
if (sourcePropType !== errorType && targetPropType !== errorType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
1094210943
const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined);
1094310944
if (elaborated) {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts(2,5): error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type 'T'.
2+
tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts(6,5): error TS2322: Type '{ a: number; }' is not assignable to type 'T'.
3+
tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts(10,5): error TS2322: Type '{ a: string; }' is not assignable to type 'T'.
4+
5+
6+
==== tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts (3 errors) ====
7+
function foo<T extends { a: string }>(x: T) {
8+
x = { a: "abc", b: 20, c: 30 };
9+
~
10+
!!! error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type 'T'.
11+
}
12+
13+
function bar<T extends { a: string }>(x: T) {
14+
x = { a: 20 };
15+
~
16+
!!! error TS2322: Type '{ a: number; }' is not assignable to type 'T'.
17+
}
18+
19+
function baz<T extends { a: string }>(x: T) {
20+
x = { a: "not ok" };
21+
~
22+
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'T'.
23+
}
24+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [errorElaborationDivesIntoApparentlyPresentPropsOnly.ts]
2+
function foo<T extends { a: string }>(x: T) {
3+
x = { a: "abc", b: 20, c: 30 };
4+
}
5+
6+
function bar<T extends { a: string }>(x: T) {
7+
x = { a: 20 };
8+
}
9+
10+
function baz<T extends { a: string }>(x: T) {
11+
x = { a: "not ok" };
12+
}
13+
14+
15+
//// [errorElaborationDivesIntoApparentlyPresentPropsOnly.js]
16+
function foo(x) {
17+
x = { a: "abc", b: 20, c: 30 };
18+
}
19+
function bar(x) {
20+
x = { a: 20 };
21+
}
22+
function baz(x) {
23+
x = { a: "not ok" };
24+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
=== tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts ===
2+
function foo<T extends { a: string }>(x: T) {
3+
>foo : Symbol(foo, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 0))
4+
>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 13))
5+
>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 24))
6+
>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 38))
7+
>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 13))
8+
9+
x = { a: "abc", b: 20, c: 30 };
10+
>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 38))
11+
>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 1, 9))
12+
>b : Symbol(b, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 1, 19))
13+
>c : Symbol(c, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 1, 26))
14+
}
15+
16+
function bar<T extends { a: string }>(x: T) {
17+
>bar : Symbol(bar, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 2, 1))
18+
>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 13))
19+
>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 24))
20+
>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 38))
21+
>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 13))
22+
23+
x = { a: 20 };
24+
>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 38))
25+
>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 5, 9))
26+
}
27+
28+
function baz<T extends { a: string }>(x: T) {
29+
>baz : Symbol(baz, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 6, 1))
30+
>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 13))
31+
>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 24))
32+
>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 38))
33+
>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 13))
34+
35+
x = { a: "not ok" };
36+
>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 38))
37+
>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 9, 9))
38+
}
39+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
=== tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts ===
2+
function foo<T extends { a: string }>(x: T) {
3+
>foo : <T extends { a: string; }>(x: T) => void
4+
>a : string
5+
>x : T
6+
7+
x = { a: "abc", b: 20, c: 30 };
8+
>x = { a: "abc", b: 20, c: 30 } : { a: string; b: number; c: number; }
9+
>x : T
10+
>{ a: "abc", b: 20, c: 30 } : { a: string; b: number; c: number; }
11+
>a : string
12+
>"abc" : "abc"
13+
>b : number
14+
>20 : 20
15+
>c : number
16+
>30 : 30
17+
}
18+
19+
function bar<T extends { a: string }>(x: T) {
20+
>bar : <T extends { a: string; }>(x: T) => void
21+
>a : string
22+
>x : T
23+
24+
x = { a: 20 };
25+
>x = { a: 20 } : { a: number; }
26+
>x : T
27+
>{ a: 20 } : { a: number; }
28+
>a : number
29+
>20 : 20
30+
}
31+
32+
function baz<T extends { a: string }>(x: T) {
33+
>baz : <T extends { a: string; }>(x: T) => void
34+
>a : string
35+
>x : T
36+
37+
x = { a: "not ok" };
38+
>x = { a: "not ok" } : { a: string; }
39+
>x : T
40+
>{ a: "not ok" } : { a: string; }
41+
>a : string
42+
>"not ok" : "not ok"
43+
}
44+

tests/baselines/reference/indexedAccessRelation.errors.txt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
tests/cases/compiler/indexedAccessRelation.ts(16,25): error TS2322: Type 'T' is not assignable to type 'S["a"] & T'.
2-
Type 'Foo' is not assignable to type 'S["a"] & T'.
3-
Type 'Foo' is not assignable to type 'S["a"]'.
4-
Type 'T' is not assignable to type 'S["a"]'.
1+
tests/cases/compiler/indexedAccessRelation.ts(16,23): error TS2345: Argument of type '{ a: T; }' is not assignable to parameter of type 'Pick<S & State<T>, "a">'.
2+
Types of property 'a' are incompatible.
3+
Type 'T' is not assignable to type 'S["a"] & T'.
4+
Type 'Foo' is not assignable to type 'S["a"] & T'.
55
Type 'Foo' is not assignable to type 'S["a"]'.
6+
Type 'T' is not assignable to type 'S["a"]'.
7+
Type 'Foo' is not assignable to type 'S["a"]'.
68

79

810
==== tests/cases/compiler/indexedAccessRelation.ts (1 errors) ====
@@ -22,13 +24,14 @@ tests/cases/compiler/indexedAccessRelation.ts(16,25): error TS2322: Type 'T' is
2224
{
2325
foo(a: T) {
2426
this.setState({ a: a });
25-
~
26-
!!! error TS2322: Type 'T' is not assignable to type 'S["a"] & T'.
27-
!!! error TS2322: Type 'Foo' is not assignable to type 'S["a"] & T'.
28-
!!! error TS2322: Type 'Foo' is not assignable to type 'S["a"]'.
29-
!!! error TS2322: Type 'T' is not assignable to type 'S["a"]'.
30-
!!! error TS2322: Type 'Foo' is not assignable to type 'S["a"]'.
31-
!!! related TS6500 tests/cases/compiler/indexedAccessRelation.ts:8:5: The expected type comes from property 'a' which is declared here on type 'Pick<S & State<T>, "a">'
27+
~~~~~~~~
28+
!!! error TS2345: Argument of type '{ a: T; }' is not assignable to parameter of type 'Pick<S & State<T>, "a">'.
29+
!!! error TS2345: Types of property 'a' are incompatible.
30+
!!! error TS2345: Type 'T' is not assignable to type 'S["a"] & T'.
31+
!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"] & T'.
32+
!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"]'.
33+
!!! error TS2345: Type 'T' is not assignable to type 'S["a"]'.
34+
!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"]'.
3235
}
3336
}
3437

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function foo<T extends { a: string }>(x: T) {
2+
x = { a: "abc", b: 20, c: 30 };
3+
}
4+
5+
function bar<T extends { a: string }>(x: T) {
6+
x = { a: 20 };
7+
}
8+
9+
function baz<T extends { a: string }>(x: T) {
10+
x = { a: "not ok" };
11+
}

0 commit comments

Comments
 (0)