From f5190d1a5602ce81811627c3139bd299ddb16e39 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 5 Oct 2018 11:10:50 -0700 Subject: [PATCH] Elt access assignment uses declared, not narrowed type I forgot to do this in #26424. Fixes #27557 Fixes #27412 --- src/compiler/checker.ts | 4 +- .../checkJsxChildrenCanBeTupleType.js | 2 +- .../reference/controlFlowElementAccess.js | 21 +++++++++ .../controlFlowElementAccess.symbols | 27 +++++++++++ .../reference/controlFlowElementAccess.types | 45 +++++++++++++++++++ .../unionTypeWithIndexSignature.errors.txt | 5 +-- .../unionTypeWithIndexSignature.types | 2 +- .../controlFlow/controlFlowElementAccess.ts | 9 ++++ 8 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/controlFlowElementAccess.js create mode 100644 tests/baselines/reference/controlFlowElementAccess.symbols create mode 100644 tests/baselines/reference/controlFlowElementAccess.types create mode 100644 tests/cases/conformance/controlFlow/controlFlowElementAccess.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ead2b14410583..c2d8af2409ed3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9305,7 +9305,9 @@ namespace ts { } } const propType = getTypeOfSymbol(prop); - return accessExpression ? getFlowTypeOfReference(accessExpression, propType) : propType; + return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ? + getFlowTypeOfReference(accessExpression, propType) : + propType; } if (isTupleType(objectType)) { const restType = getRestTypeOfTupleType(objectType); diff --git a/tests/baselines/reference/checkJsxChildrenCanBeTupleType.js b/tests/baselines/reference/checkJsxChildrenCanBeTupleType.js index a116e7ad29a31..30e59613eb902 100644 --- a/tests/baselines/reference/checkJsxChildrenCanBeTupleType.js +++ b/tests/baselines/reference/checkJsxChildrenCanBeTupleType.js @@ -30,7 +30,7 @@ var __extends = (this && this.__extends) || (function () { ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); - } + }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } diff --git a/tests/baselines/reference/controlFlowElementAccess.js b/tests/baselines/reference/controlFlowElementAccess.js new file mode 100644 index 0000000000000..a68809623437a --- /dev/null +++ b/tests/baselines/reference/controlFlowElementAccess.js @@ -0,0 +1,21 @@ +//// [controlFlowElementAccess.ts] +let x: { o: boolean } = { o: false } +if (x['o'] === false) { + x['o'] = true +} + +const y: [number, number] = [0, 0]; +if (y[0] === 0) { + y[0] = -1; +} + + +//// [controlFlowElementAccess.js] +var x = { o: false }; +if (x['o'] === false) { + x['o'] = true; +} +var y = [0, 0]; +if (y[0] === 0) { + y[0] = -1; +} diff --git a/tests/baselines/reference/controlFlowElementAccess.symbols b/tests/baselines/reference/controlFlowElementAccess.symbols new file mode 100644 index 0000000000000..0def458ced5f7 --- /dev/null +++ b/tests/baselines/reference/controlFlowElementAccess.symbols @@ -0,0 +1,27 @@ +=== tests/cases/conformance/controlFlow/controlFlowElementAccess.ts === +let x: { o: boolean } = { o: false } +>x : Symbol(x, Decl(controlFlowElementAccess.ts, 0, 3)) +>o : Symbol(o, Decl(controlFlowElementAccess.ts, 0, 8)) +>o : Symbol(o, Decl(controlFlowElementAccess.ts, 0, 25)) + +if (x['o'] === false) { +>x : Symbol(x, Decl(controlFlowElementAccess.ts, 0, 3)) +>'o' : Symbol(o, Decl(controlFlowElementAccess.ts, 0, 8)) + + x['o'] = true +>x : Symbol(x, Decl(controlFlowElementAccess.ts, 0, 3)) +>'o' : Symbol(o, Decl(controlFlowElementAccess.ts, 0, 8)) +} + +const y: [number, number] = [0, 0]; +>y : Symbol(y, Decl(controlFlowElementAccess.ts, 5, 5)) + +if (y[0] === 0) { +>y : Symbol(y, Decl(controlFlowElementAccess.ts, 5, 5)) +>0 : Symbol(0) + + y[0] = -1; +>y : Symbol(y, Decl(controlFlowElementAccess.ts, 5, 5)) +>0 : Symbol(0) +} + diff --git a/tests/baselines/reference/controlFlowElementAccess.types b/tests/baselines/reference/controlFlowElementAccess.types new file mode 100644 index 0000000000000..9c885326dc2c5 --- /dev/null +++ b/tests/baselines/reference/controlFlowElementAccess.types @@ -0,0 +1,45 @@ +=== tests/cases/conformance/controlFlow/controlFlowElementAccess.ts === +let x: { o: boolean } = { o: false } +>x : { o: boolean; } +>o : boolean +>{ o: false } : { o: false; } +>o : false +>false : false + +if (x['o'] === false) { +>x['o'] === false : boolean +>x['o'] : boolean +>x : { o: boolean; } +>'o' : "o" +>false : false + + x['o'] = true +>x['o'] = true : true +>x['o'] : boolean +>x : { o: boolean; } +>'o' : "o" +>true : true +} + +const y: [number, number] = [0, 0]; +>y : [number, number] +>[0, 0] : [number, number] +>0 : 0 +>0 : 0 + +if (y[0] === 0) { +>y[0] === 0 : boolean +>y[0] : number +>y : [number, number] +>0 : 0 +>0 : 0 + + y[0] = -1; +>y[0] = -1 : -1 +>y[0] : number +>y : [number, number] +>0 : 0 +>-1 : -1 +>1 : 1 +} + diff --git a/tests/baselines/reference/unionTypeWithIndexSignature.errors.txt b/tests/baselines/reference/unionTypeWithIndexSignature.errors.txt index 7f4675b0373a3..e95a184d15a5b 100644 --- a/tests/baselines/reference/unionTypeWithIndexSignature.errors.txt +++ b/tests/baselines/reference/unionTypeWithIndexSignature.errors.txt @@ -1,13 +1,12 @@ tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts(11,3): error TS2339: Property 'bar' does not exist on type 'Missing'. Property 'bar' does not exist on type '{ [s: string]: string; }'. tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts(14,4): error TS2540: Cannot assign to 'foo' because it is a constant or a read-only property. -tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts(18,1): error TS2322: Type '"ok"' is not assignable to type 'number'. tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts(24,1): error TS7017: Element implicitly has an 'any' type because type 'Both' has no index signature. tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts(25,1): error TS2322: Type '"not ok"' is not assignable to type 'number'. tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts(26,1): error TS7017: Element implicitly has an 'any' type because type 'Both' has no index signature. -==== tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts (6 errors) ==== +==== tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts (5 errors) ==== type Two = { foo: { bar: true }, baz: true } | { [s: string]: string }; declare var u: Two u.foo = 'bye' @@ -31,8 +30,6 @@ tests/cases/conformance/types/union/unionTypeWithIndexSignature.ts(26,1): error declare var num: Num num[0] = 1 num['0'] = 'ok' - ~~~~~~~~ -!!! error TS2322: Type '"ok"' is not assignable to type 'number'. const sym = Symbol() type Both = { s: number, '0': number, [sym]: boolean } | { [n: number]: number, [s: string]: string | number } declare var both: Both diff --git a/tests/baselines/reference/unionTypeWithIndexSignature.types b/tests/baselines/reference/unionTypeWithIndexSignature.types index a699d51391cc2..417d62e706e9a 100644 --- a/tests/baselines/reference/unionTypeWithIndexSignature.types +++ b/tests/baselines/reference/unionTypeWithIndexSignature.types @@ -96,7 +96,7 @@ num[0] = 1 num['0'] = 'ok' >num['0'] = 'ok' : "ok" ->num['0'] : number +>num['0'] : string | number >num : Num >'0' : "0" >'ok' : "ok" diff --git a/tests/cases/conformance/controlFlow/controlFlowElementAccess.ts b/tests/cases/conformance/controlFlow/controlFlowElementAccess.ts new file mode 100644 index 0000000000000..eb802e3083c1a --- /dev/null +++ b/tests/cases/conformance/controlFlow/controlFlowElementAccess.ts @@ -0,0 +1,9 @@ +let x: { o: boolean } = { o: false } +if (x['o'] === false) { + x['o'] = true +} + +const y: [number, number] = [0, 0]; +if (y[0] === 0) { + y[0] = -1; +}