From d7390c03f0048d4accdd54b163c4e12343c3ef02 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 6 Nov 2018 12:51:11 -0800 Subject: [PATCH] Avoid elaborating on generic indexes (#28294) --- src/compiler/checker.ts | 3 +- ...sIntoApparentlyPresentPropsOnly.errors.txt | 24 ++++++++++ ...tionDivesIntoApparentlyPresentPropsOnly.js | 24 ++++++++++ ...ivesIntoApparentlyPresentPropsOnly.symbols | 39 ++++++++++++++++ ...nDivesIntoApparentlyPresentPropsOnly.types | 44 +++++++++++++++++++ .../indexedAccessRelation.errors.txt | 25 ++++++----- ...tionDivesIntoApparentlyPresentPropsOnly.ts | 11 +++++ 7 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.errors.txt create mode 100644 tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.js create mode 100644 tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.symbols create mode 100644 tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.types create mode 100644 tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6260a958d..cd29b9450b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10936,8 +10936,9 @@ namespace ts { let reportedError = false; for (let status = iterator.next(); !status.done; status = iterator.next()) { const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value; - const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType); const targetPropType = getIndexedAccessType(target, nameType, /*accessNode*/ undefined, errorType); + if (targetPropType === errorType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables + const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType); if (sourcePropType !== errorType && targetPropType !== errorType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) { const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined); if (elaborated) { diff --git a/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.errors.txt b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.errors.txt new file mode 100644 index 0000000000..e2b18aa2fc --- /dev/null +++ b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.errors.txt @@ -0,0 +1,24 @@ +tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts(2,5): error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type 'T'. +tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts(6,5): error TS2322: Type '{ a: number; }' is not assignable to type 'T'. +tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts(10,5): error TS2322: Type '{ a: string; }' is not assignable to type 'T'. + + +==== tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts (3 errors) ==== + function foo(x: T) { + x = { a: "abc", b: 20, c: 30 }; + ~ +!!! error TS2322: Type '{ a: string; b: number; c: number; }' is not assignable to type 'T'. + } + + function bar(x: T) { + x = { a: 20 }; + ~ +!!! error TS2322: Type '{ a: number; }' is not assignable to type 'T'. + } + + function baz(x: T) { + x = { a: "not ok" }; + ~ +!!! error TS2322: Type '{ a: string; }' is not assignable to type 'T'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.js b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.js new file mode 100644 index 0000000000..bdf87a0acc --- /dev/null +++ b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.js @@ -0,0 +1,24 @@ +//// [errorElaborationDivesIntoApparentlyPresentPropsOnly.ts] +function foo(x: T) { + x = { a: "abc", b: 20, c: 30 }; +} + +function bar(x: T) { + x = { a: 20 }; +} + +function baz(x: T) { + x = { a: "not ok" }; +} + + +//// [errorElaborationDivesIntoApparentlyPresentPropsOnly.js] +function foo(x) { + x = { a: "abc", b: 20, c: 30 }; +} +function bar(x) { + x = { a: 20 }; +} +function baz(x) { + x = { a: "not ok" }; +} diff --git a/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.symbols b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.symbols new file mode 100644 index 0000000000..8ad2996d7f --- /dev/null +++ b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.symbols @@ -0,0 +1,39 @@ +=== tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts === +function foo(x: T) { +>foo : Symbol(foo, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 0)) +>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 13)) +>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 24)) +>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 38)) +>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 13)) + + x = { a: "abc", b: 20, c: 30 }; +>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 0, 38)) +>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 1, 9)) +>b : Symbol(b, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 1, 19)) +>c : Symbol(c, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 1, 26)) +} + +function bar(x: T) { +>bar : Symbol(bar, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 2, 1)) +>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 13)) +>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 24)) +>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 38)) +>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 13)) + + x = { a: 20 }; +>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 4, 38)) +>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 5, 9)) +} + +function baz(x: T) { +>baz : Symbol(baz, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 6, 1)) +>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 13)) +>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 24)) +>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 38)) +>T : Symbol(T, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 13)) + + x = { a: "not ok" }; +>x : Symbol(x, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 8, 38)) +>a : Symbol(a, Decl(errorElaborationDivesIntoApparentlyPresentPropsOnly.ts, 9, 9)) +} + diff --git a/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.types b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.types new file mode 100644 index 0000000000..1393814ffe --- /dev/null +++ b/tests/baselines/reference/errorElaborationDivesIntoApparentlyPresentPropsOnly.types @@ -0,0 +1,44 @@ +=== tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts === +function foo(x: T) { +>foo : (x: T) => void +>a : string +>x : T + + x = { a: "abc", b: 20, c: 30 }; +>x = { a: "abc", b: 20, c: 30 } : { a: string; b: number; c: number; } +>x : T +>{ a: "abc", b: 20, c: 30 } : { a: string; b: number; c: number; } +>a : string +>"abc" : "abc" +>b : number +>20 : 20 +>c : number +>30 : 30 +} + +function bar(x: T) { +>bar : (x: T) => void +>a : string +>x : T + + x = { a: 20 }; +>x = { a: 20 } : { a: number; } +>x : T +>{ a: 20 } : { a: number; } +>a : number +>20 : 20 +} + +function baz(x: T) { +>baz : (x: T) => void +>a : string +>x : T + + x = { a: "not ok" }; +>x = { a: "not ok" } : { a: string; } +>x : T +>{ a: "not ok" } : { a: string; } +>a : string +>"not ok" : "not ok" +} + diff --git a/tests/baselines/reference/indexedAccessRelation.errors.txt b/tests/baselines/reference/indexedAccessRelation.errors.txt index 14dbee4d4c..84e65df856 100644 --- a/tests/baselines/reference/indexedAccessRelation.errors.txt +++ b/tests/baselines/reference/indexedAccessRelation.errors.txt @@ -1,8 +1,10 @@ -tests/cases/compiler/indexedAccessRelation.ts(16,25): error TS2322: Type 'T' is not assignable to type 'S["a"] & T'. - Type 'Foo' is not assignable to type 'S["a"] & T'. - Type 'Foo' is not assignable to type 'S["a"]'. - Type 'T' is not assignable to type 'S["a"]'. +tests/cases/compiler/indexedAccessRelation.ts(16,23): error TS2345: Argument of type '{ a: T; }' is not assignable to parameter of type 'Pick, "a">'. + Types of property 'a' are incompatible. + Type 'T' is not assignable to type 'S["a"] & T'. + Type 'Foo' is not assignable to type 'S["a"] & T'. Type 'Foo' is not assignable to type 'S["a"]'. + Type 'T' is not assignable to type 'S["a"]'. + Type 'Foo' is not assignable to type 'S["a"]'. ==== tests/cases/compiler/indexedAccessRelation.ts (1 errors) ==== @@ -22,13 +24,14 @@ tests/cases/compiler/indexedAccessRelation.ts(16,25): error TS2322: Type 'T' is { foo(a: T) { this.setState({ a: a }); - ~ -!!! error TS2322: Type 'T' is not assignable to type 'S["a"] & T'. -!!! error TS2322: Type 'Foo' is not assignable to type 'S["a"] & T'. -!!! error TS2322: Type 'Foo' is not assignable to type 'S["a"]'. -!!! error TS2322: Type 'T' is not assignable to type 'S["a"]'. -!!! error TS2322: Type 'Foo' is not assignable to type 'S["a"]'. -!!! related TS6500 tests/cases/compiler/indexedAccessRelation.ts:8:5: The expected type comes from property 'a' which is declared here on type 'Pick, "a">' + ~~~~~~~~ +!!! error TS2345: Argument of type '{ a: T; }' is not assignable to parameter of type 'Pick, "a">'. +!!! error TS2345: Types of property 'a' are incompatible. +!!! error TS2345: Type 'T' is not assignable to type 'S["a"] & T'. +!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"] & T'. +!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"]'. +!!! error TS2345: Type 'T' is not assignable to type 'S["a"]'. +!!! error TS2345: Type 'Foo' is not assignable to type 'S["a"]'. } } \ No newline at end of file diff --git a/tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts b/tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts new file mode 100644 index 0000000000..1045fd95ca --- /dev/null +++ b/tests/cases/compiler/errorElaborationDivesIntoApparentlyPresentPropsOnly.ts @@ -0,0 +1,11 @@ +function foo(x: T) { + x = { a: "abc", b: 20, c: 30 }; +} + +function bar(x: T) { + x = { a: 20 }; +} + +function baz(x: T) { + x = { a: "not ok" }; +}