From 5966bcac6b19680587f9a5071214a85444e9d483 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Sat, 25 Sep 2021 20:29:07 +0300 Subject: [PATCH] fix(40617): handle uninitialized class member with computed key --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 34 ++- src/compiler/commandLineParser.ts | 2 +- .../controlFlowOptionalChain.errors.txt | 5 +- .../reference/controlFlowOptionalChain.types | 4 +- .../reference/incrementOnNullAssertion.types | 10 +- .../noUncheckedIndexedAccess.errors.txt | 6 +- .../reference/noUncheckedIndexedAccess.types | 2 +- .../strictPropertyInitialization.errors.txt | 15 + .../reference/strictPropertyInitialization.js | 32 ++ .../strictPropertyInitialization.symbols | 37 +++ .../strictPropertyInitialization.types | 48 +++ ...rdNarrowsIndexedAccessOfKnownProperty1.js} | 4 +- ...rowsIndexedAccessOfKnownProperty1.symbols} | 282 +++++++++--------- ...arrowsIndexedAccessOfKnownProperty1.types} | 2 +- ...ardNarrowsIndexedAccessOfKnownProperty2.js | 18 ++ ...rrowsIndexedAccessOfKnownProperty2.symbols | 23 ++ ...NarrowsIndexedAccessOfKnownProperty2.types | 27 ++ ...ardNarrowsIndexedAccessOfKnownProperty3.js | 18 ++ ...rrowsIndexedAccessOfKnownProperty3.symbols | 25 ++ ...NarrowsIndexedAccessOfKnownProperty3.types | 38 +++ ...ardNarrowsIndexedAccessOfKnownProperty4.js | 20 ++ ...rrowsIndexedAccessOfKnownProperty4.symbols | 27 ++ ...NarrowsIndexedAccessOfKnownProperty4.types | 35 +++ ...ardNarrowsIndexedAccessOfKnownProperty5.js | 28 ++ ...rrowsIndexedAccessOfKnownProperty5.symbols | 31 ++ ...NarrowsIndexedAccessOfKnownProperty5.types | 36 +++ ...rdNarrowsIndexedAccessOfKnownProperty1.ts} | 0 ...ardNarrowsIndexedAccessOfKnownProperty2.ts | 9 + ...ardNarrowsIndexedAccessOfKnownProperty3.ts | 10 + ...ardNarrowsIndexedAccessOfKnownProperty4.ts | 9 + ...ardNarrowsIndexedAccessOfKnownProperty5.ts | 15 + .../strictPropertyInitialization.ts | 17 +- 33 files changed, 703 insertions(+), 168 deletions(-) rename tests/baselines/reference/{typeGuardNarrowsIndexedAccessOfKnownProperty.js => typeGuardNarrowsIndexedAccessOfKnownProperty1.js} (95%) rename tests/baselines/reference/{typeGuardNarrowsIndexedAccessOfKnownProperty.symbols => typeGuardNarrowsIndexedAccessOfKnownProperty1.symbols} (73%) rename tests/baselines/reference/{typeGuardNarrowsIndexedAccessOfKnownProperty.types => typeGuardNarrowsIndexedAccessOfKnownProperty1.types} (95%) create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.js create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.symbols create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.types create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.js create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.symbols create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.types create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.js create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.symbols create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.types create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.js create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.symbols create mode 100644 tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.types rename tests/cases/compiler/{typeGuardNarrowsIndexedAccessOfKnownProperty.ts => typeGuardNarrowsIndexedAccessOfKnownProperty1.ts} (100%) create mode 100644 tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty2.ts create mode 100644 tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty3.ts create mode 100644 tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty4.ts create mode 100644 tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty5.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index d26da9bcbf082..7389765cce23b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -889,7 +889,7 @@ namespace ts { return isDottedName(expr) || (isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) || isBinaryExpression(expr) && expr.operatorToken.kind === SyntaxKind.CommaToken && isNarrowableReference(expr.right) - || isElementAccessExpression(expr) && isStringOrNumericLiteralLike(expr.argumentExpression) && isNarrowableReference(expr.expression) + || isElementAccessExpression(expr) && (isStringOrNumericLiteralLike(expr.argumentExpression) || isIdentifier(expr.argumentExpression)) && isNarrowableReference(expr.expression) || isAssignmentExpression(expr) && isNarrowableReference(expr.left); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 20078bc12d87a..72e7ae73397c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22396,11 +22396,27 @@ namespace ts { } function getAccessedPropertyName(access: AccessExpression | BindingElement): __String | undefined { - let propertyName; - return access.kind === SyntaxKind.PropertyAccessExpression ? access.name.escapedText : - access.kind === SyntaxKind.ElementAccessExpression && isStringOrNumericLiteralLike(access.argumentExpression) ? escapeLeadingUnderscores(access.argumentExpression.text) : - access.kind === SyntaxKind.BindingElement && (propertyName = getDestructuringPropertyName(access)) ? escapeLeadingUnderscores(propertyName) : - undefined; + if (isPropertyAccessExpression(access)) { + return access.name.escapedText; + } + if (isElementAccessExpression(access)) { + if (isStringOrNumericLiteralLike(access.argumentExpression)) { + return escapeLeadingUnderscores(access.argumentExpression.text); + } + if (isIdentifier(access.argumentExpression)) { + const symbol = getResolvedSymbol(access.argumentExpression); + const type = getSymbolLinks(symbol).type; + if (type === undefined) return undefined; + return type.flags & TypeFlags.UniqueESSymbol ? (type as UniqueESSymbolType).escapedName : + type.flags & TypeFlags.StringOrNumberLiteral ? escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value) : undefined; + } + return undefined; + } + if (isBindingElement(access)) { + const name = getDestructuringPropertyName(access); + return name ? escapeLeadingUnderscores(name) : undefined; + } + return undefined; } function containsMatchingReference(source: Node, target: Node) { @@ -38598,7 +38614,7 @@ namespace ts { } if (!isStatic(member) && isPropertyWithoutInitializer(member)) { const propName = (member as PropertyDeclaration).name; - if (isIdentifier(propName) || isPrivateIdentifier(propName)) { + if (isIdentifier(propName) || isPrivateIdentifier(propName) || isComputedPropertyName(propName)) { const type = getTypeOfSymbol(getSymbolOfNode(member)); if (!(type.flags & TypeFlags.AnyOrUnknown || getFalsyFlags(type) & TypeFlags.Undefined)) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { @@ -38634,8 +38650,10 @@ namespace ts { return false; } - function isPropertyInitializedInConstructor(propName: Identifier | PrivateIdentifier, propType: Type, constructor: ConstructorDeclaration) { - const reference = factory.createPropertyAccessExpression(factory.createThis(), propName); + function isPropertyInitializedInConstructor(propName: Identifier | PrivateIdentifier | ComputedPropertyName, propType: Type, constructor: ConstructorDeclaration) { + const reference = isComputedPropertyName(propName) + ? factory.createElementAccessExpression(factory.createThis(), propName.expression) + : factory.createPropertyAccessExpression(factory.createThis(), propName); setParent(reference.expression, reference); setParent(reference, constructor); reference.flowNode = constructor.returnFlowNode; diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 118b72e252a94..98719a8d78f34 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -2686,7 +2686,7 @@ namespace ts { function getPropFromRaw(prop: "files" | "include" | "exclude" | "references", validateElement: (value: unknown) => boolean, elementTypeName: string): PropOfRaw { if (hasProperty(raw, prop) && !isNullOrUndefined(raw[prop])) { if (isArray(raw[prop])) { - const result = raw[prop]; + const result = raw[prop] as T[]; if (!sourceFile && !every(result, validateElement)) { errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, elementTypeName)); } diff --git a/tests/baselines/reference/controlFlowOptionalChain.errors.txt b/tests/baselines/reference/controlFlowOptionalChain.errors.txt index 1dfe8e9e328a0..cc992d9d002ee 100644 --- a/tests/baselines/reference/controlFlowOptionalChain.errors.txt +++ b/tests/baselines/reference/controlFlowOptionalChain.errors.txt @@ -59,9 +59,10 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(501,13): error T tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(515,13): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(518,13): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(586,9): error TS2367: This condition will always return 'false' since the types '"left"' and '"right"' have no overlap. -==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (61 errors) ==== +==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (62 errors) ==== // assignments in shortcutting chain declare const o: undefined | { [key: string]: any; @@ -770,6 +771,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T while (arr[i]?.tag === "left") { i += 1; if (arr[i]?.tag === "right") { + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2367: This condition will always return 'false' since the types '"left"' and '"right"' have no overlap. console.log("I should ALSO be reachable"); } } diff --git a/tests/baselines/reference/controlFlowOptionalChain.types b/tests/baselines/reference/controlFlowOptionalChain.types index 4e335fca6d287..b144ef2954430 100644 --- a/tests/baselines/reference/controlFlowOptionalChain.types +++ b/tests/baselines/reference/controlFlowOptionalChain.types @@ -2057,11 +2057,11 @@ while (arr[i]?.tag === "left") { if (arr[i]?.tag === "right") { >arr[i]?.tag === "right" : boolean ->arr[i]?.tag : "left" | "right" +>arr[i]?.tag : "left" >arr[i] : { tag: "left" | "right"; } >arr : { tag: "left" | "right"; }[] >i : number ->tag : "left" | "right" +>tag : "left" >"right" : "right" console.log("I should ALSO be reachable"); diff --git a/tests/baselines/reference/incrementOnNullAssertion.types b/tests/baselines/reference/incrementOnNullAssertion.types index 0c7f5340b9f9a..199c4c87050f8 100644 --- a/tests/baselines/reference/incrementOnNullAssertion.types +++ b/tests/baselines/reference/incrementOnNullAssertion.types @@ -27,21 +27,21 @@ if (foo[x] === undefined) { } else { let nu = foo[x] ->nu : number | undefined ->foo[x] : number | undefined +>nu : number +>foo[x] : number >foo : Dictionary >x : "bar" let n = foo[x] ->n : number | undefined ->foo[x] : number | undefined +>n : number +>foo[x] : number >foo : Dictionary >x : "bar" foo[x]!++ >foo[x]!++ : number >foo[x]! : number ->foo[x] : number | undefined +>foo[x] : number >foo : Dictionary >x : "bar" } diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt b/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt index 39a4e9aeb4442..ff6d730d3cdc9 100644 --- a/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt +++ b/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt @@ -32,8 +32,7 @@ tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(90,7): error TS2322 Type 'undefined' is not assignable to type 'string'. tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(98,5): error TS2322: Type 'undefined' is not assignable to type '{ [key: string]: string; a: string; b: string; }[Key]'. Type 'undefined' is not assignable to type 'string'. -tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(99,11): error TS2322: Type 'string | undefined' is not assignable to type 'string'. - Type 'undefined' is not assignable to type 'string'. +tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(99,11): error TS2322: Type 'undefined' is not assignable to type 'string'. ==== tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts (31 errors) ==== @@ -201,8 +200,7 @@ tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(99,11): error TS232 !!! error TS2322: Type 'undefined' is not assignable to type 'string'. const v: string = myRecord2[key]; // Should error ~ -!!! error TS2322: Type 'string | undefined' is not assignable to type 'string'. -!!! error TS2322: Type 'undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. }; \ No newline at end of file diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.types b/tests/baselines/reference/noUncheckedIndexedAccess.types index 9dc76ff0d887a..e472de4eb5482 100644 --- a/tests/baselines/reference/noUncheckedIndexedAccess.types +++ b/tests/baselines/reference/noUncheckedIndexedAccess.types @@ -412,7 +412,7 @@ const fn3 = (key: Key) => { const v: string = myRecord2[key]; // Should error >v : string ->myRecord2[key] : string | undefined +>myRecord2[key] : undefined >myRecord2 : { [key: string]: string; a: string; b: string; } >key : Key diff --git a/tests/baselines/reference/strictPropertyInitialization.errors.txt b/tests/baselines/reference/strictPropertyInitialization.errors.txt index aca8b44e0737c..208c0a32e4d1d 100644 --- a/tests/baselines/reference/strictPropertyInitialization.errors.txt +++ b/tests/baselines/reference/strictPropertyInitialization.errors.txt @@ -164,4 +164,19 @@ tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitial this.#b = someValue(); } } + + const a = 'a'; + const b = Symbol(); + + class C12 { + [a]: number; + [b]: number; + ['c']: number; + + constructor() { + this[a] = 1; + this[b] = 1; + this['c'] = 1; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/strictPropertyInitialization.js b/tests/baselines/reference/strictPropertyInitialization.js index 30867a3773de1..41760958edd1f 100644 --- a/tests/baselines/reference/strictPropertyInitialization.js +++ b/tests/baselines/reference/strictPropertyInitialization.js @@ -132,6 +132,21 @@ class C11 { this.#b = someValue(); } } + +const a = 'a'; +const b = Symbol(); + +class C12 { + [a]: number; + [b]: number; + ['c']: number; + + constructor() { + this[a] = 1; + this[b] = 1; + this['c'] = 1; + } +} //// [strictPropertyInitialization.js] @@ -235,6 +250,15 @@ class C11 { } } _C11_b = new WeakMap(); +const a = 'a'; +const b = Symbol(); +class C12 { + constructor() { + this[a] = 1; + this[b] = 1; + this['c'] = 1; + } +} //// [strictPropertyInitialization.d.ts] @@ -303,3 +327,11 @@ declare class C11 { a: number; constructor(); } +declare const a = "a"; +declare const b: unique symbol; +declare class C12 { + [a]: number; + [b]: number; + ['c']: number; + constructor(); +} diff --git a/tests/baselines/reference/strictPropertyInitialization.symbols b/tests/baselines/reference/strictPropertyInitialization.symbols index 2f1e4b9fbeceb..45e15f21403e5 100644 --- a/tests/baselines/reference/strictPropertyInitialization.symbols +++ b/tests/baselines/reference/strictPropertyInitialization.symbols @@ -311,3 +311,40 @@ class C11 { } } +const a = 'a'; +>a : Symbol(a, Decl(strictPropertyInitialization.ts, 134, 5)) + +const b = Symbol(); +>b : Symbol(b, Decl(strictPropertyInitialization.ts, 135, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +class C12 { +>C12 : Symbol(C12, Decl(strictPropertyInitialization.ts, 135, 19)) + + [a]: number; +>[a] : Symbol(C12[a], Decl(strictPropertyInitialization.ts, 137, 11)) +>a : Symbol(a, Decl(strictPropertyInitialization.ts, 134, 5)) + + [b]: number; +>[b] : Symbol(C12[b], Decl(strictPropertyInitialization.ts, 138, 16)) +>b : Symbol(b, Decl(strictPropertyInitialization.ts, 135, 5)) + + ['c']: number; +>['c'] : Symbol(C12['c'], Decl(strictPropertyInitialization.ts, 139, 16)) +>'c' : Symbol(C12['c'], Decl(strictPropertyInitialization.ts, 139, 16)) + + constructor() { + this[a] = 1; +>this : Symbol(C12, Decl(strictPropertyInitialization.ts, 135, 19)) +>a : Symbol(a, Decl(strictPropertyInitialization.ts, 134, 5)) + + this[b] = 1; +>this : Symbol(C12, Decl(strictPropertyInitialization.ts, 135, 19)) +>b : Symbol(b, Decl(strictPropertyInitialization.ts, 135, 5)) + + this['c'] = 1; +>this : Symbol(C12, Decl(strictPropertyInitialization.ts, 135, 19)) +>'c' : Symbol(C12['c'], Decl(strictPropertyInitialization.ts, 139, 16)) + } +} + diff --git a/tests/baselines/reference/strictPropertyInitialization.types b/tests/baselines/reference/strictPropertyInitialization.types index 8c7c20e613064..84d375c85157a 100644 --- a/tests/baselines/reference/strictPropertyInitialization.types +++ b/tests/baselines/reference/strictPropertyInitialization.types @@ -347,3 +347,51 @@ class C11 { } } +const a = 'a'; +>a : "a" +>'a' : "a" + +const b = Symbol(); +>b : unique symbol +>Symbol() : unique symbol +>Symbol : SymbolConstructor + +class C12 { +>C12 : C12 + + [a]: number; +>[a] : number +>a : "a" + + [b]: number; +>[b] : number +>b : unique symbol + + ['c']: number; +>['c'] : number +>'c' : "c" + + constructor() { + this[a] = 1; +>this[a] = 1 : 1 +>this[a] : number +>this : this +>a : "a" +>1 : 1 + + this[b] = 1; +>this[b] = 1 : 1 +>this[b] : number +>this : this +>b : unique symbol +>1 : 1 + + this['c'] = 1; +>this['c'] = 1 : 1 +>this['c'] : number +>this : this +>'c' : "c" +>1 : 1 + } +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.js b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.js similarity index 95% rename from tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.js rename to tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.js index e951538563807..47616919e1c88 100644 --- a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.js +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.js @@ -1,4 +1,4 @@ -//// [typeGuardNarrowsIndexedAccessOfKnownProperty.ts] +//// [typeGuardNarrowsIndexedAccessOfKnownProperty1.ts] interface Square { ["dash-ok"]: "square"; ["square-size"]: number; @@ -80,7 +80,7 @@ export function g(pair: [number, string?]): string { } -//// [typeGuardNarrowsIndexedAccessOfKnownProperty.js] +//// [typeGuardNarrowsIndexedAccessOfKnownProperty1.js] "use strict"; exports.__esModule = true; exports.g = void 0; diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.symbols b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.symbols similarity index 73% rename from tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.symbols rename to tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.symbols index 3a8e434aa3c80..e60a512040069 100644 --- a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.symbols +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.symbols @@ -1,254 +1,254 @@ -=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty.ts === +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty1.ts === interface Square { ->Square : Symbol(Square, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 0, 0)) +>Square : Symbol(Square, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 0, 0)) ["dash-ok"]: "square"; ->["dash-ok"] : Symbol(Square["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 0, 18)) ->"dash-ok" : Symbol(Square["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 0, 18)) +>["dash-ok"] : Symbol(Square["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 0, 18)) +>"dash-ok" : Symbol(Square["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 0, 18)) ["square-size"]: number; ->["square-size"] : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 1, 26)) ->"square-size" : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 1, 26)) +>["square-size"] : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 1, 26)) +>"square-size" : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 1, 26)) } interface Rectangle { ->Rectangle : Symbol(Rectangle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 3, 1)) +>Rectangle : Symbol(Rectangle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 3, 1)) ["dash-ok"]: "rectangle"; ->["dash-ok"] : Symbol(Rectangle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 4, 22)) ->"dash-ok" : Symbol(Rectangle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 4, 22)) +>["dash-ok"] : Symbol(Rectangle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 4, 22)) +>"dash-ok" : Symbol(Rectangle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 4, 22)) width: number; ->width : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 5, 29)) +>width : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 5, 29)) height: number; ->height : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 6, 18)) +>height : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 6, 18)) } interface Circle { ->Circle : Symbol(Circle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 8, 1)) +>Circle : Symbol(Circle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 8, 1)) ["dash-ok"]: "circle"; ->["dash-ok"] : Symbol(Circle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 9, 19)) ->"dash-ok" : Symbol(Circle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 9, 19)) +>["dash-ok"] : Symbol(Circle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 9, 19)) +>"dash-ok" : Symbol(Circle["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 9, 19)) radius: number; ->radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 10, 26)) +>radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 10, 26)) } type Shape = Square | Rectangle | Circle; ->Shape : Symbol(Shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 12, 1)) ->Square : Symbol(Square, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 0, 0)) ->Rectangle : Symbol(Rectangle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 3, 1)) ->Circle : Symbol(Circle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 8, 1)) +>Shape : Symbol(Shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 12, 1)) +>Square : Symbol(Square, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 0, 0)) +>Rectangle : Symbol(Rectangle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 3, 1)) +>Circle : Symbol(Circle, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 8, 1)) interface Subshape { ->Subshape : Symbol(Subshape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 13, 42)) +>Subshape : Symbol(Subshape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 13, 42)) "0": { ->"0" : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) +>"0" : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) sub: { ->sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) +>sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) under: { ->under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) +>under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) shape: Shape; ->shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->Shape : Symbol(Shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 12, 1)) +>shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>Shape : Symbol(Shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 12, 1)) } } } } function area(s: Shape): number { ->area : Symbol(area, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 22, 1)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->Shape : Symbol(Shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 12, 1)) +>area : Symbol(area, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 22, 1)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>Shape : Symbol(Shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 12, 1)) switch(s['dash-ok']) { ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->'dash-ok' : Symbol(["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 0, 18), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 4, 22), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 9, 19)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>'dash-ok' : Symbol(["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 0, 18), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 4, 22), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 9, 19)) case "square": return s['square-size'] * s['square-size']; ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->'square-size' : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 1, 26)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->'square-size' : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 1, 26)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>'square-size' : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 1, 26)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>'square-size' : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 1, 26)) case "rectangle": return s.width * s['height']; ->s.width : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 5, 29)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->width : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 5, 29)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->'height' : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 6, 18)) +>s.width : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 5, 29)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>width : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 5, 29)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>'height' : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 6, 18)) case "circle": return Math.PI * s['radius'] * s.radius; >Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --)) >Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->'radius' : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 10, 26)) ->s.radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 10, 26)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 23, 14)) ->radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 10, 26)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>'radius' : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 10, 26)) +>s.radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 10, 26)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 23, 14)) +>radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 10, 26)) } } function subarea(s: Subshape): number { ->subarea : Symbol(subarea, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 29, 1)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->Subshape : Symbol(Subshape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 13, 42)) +>subarea : Symbol(subarea, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 29, 1)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>Subshape : Symbol(Subshape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 13, 42)) switch(s[0]["sub"].under["shape"]["dash-ok"]) { ->s[0]["sub"].under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) ->"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->"dash-ok" : Symbol(["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 0, 18), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 4, 22), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 9, 19)) +>s[0]["sub"].under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) +>"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>"dash-ok" : Symbol(["dash-ok"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 0, 18), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 4, 22), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 9, 19)) case "square": return s[0].sub.under.shape["square-size"] * s[0].sub.under.shape["square-size"]; ->s[0].sub.under.shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->s[0].sub.under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->s[0].sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) ->sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->"square-size" : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 1, 26)) ->s[0].sub.under.shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->s[0].sub.under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->s[0].sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) ->sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->"square-size" : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 1, 26)) +>s[0].sub.under.shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>s[0].sub.under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>s[0].sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) +>sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>"square-size" : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 1, 26)) +>s[0].sub.under.shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>s[0].sub.under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>s[0].sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) +>sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>"square-size" : Symbol(Square["square-size"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 1, 26)) case "rectangle": return s[0]["sub"]["under"]["shape"]["width"] * s[0]["sub"]["under"]["shape"].height; ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) ->"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->"under" : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->"width" : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 5, 29)) ->s[0]["sub"]["under"]["shape"].height : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 6, 18)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) ->"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->"under" : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->height : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 6, 18)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) +>"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>"under" : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>"width" : Symbol(Rectangle.width, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 5, 29)) +>s[0]["sub"]["under"]["shape"].height : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 6, 18)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) +>"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>"under" : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>height : Symbol(Rectangle.height, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 6, 18)) case "circle": return Math.PI * s[0].sub.under["shape"].radius * s[0]["sub"].under.shape["radius"]; >Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --)) >Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --)) ->s[0].sub.under["shape"].radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 10, 26)) ->s[0].sub.under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->s[0].sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) ->sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 10, 26)) ->s[0]["sub"].under.shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->s[0]["sub"].under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 30, 17)) ->0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 14, 20)) ->"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 15, 10)) ->under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 16, 14)) ->shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 17, 20)) ->"radius" : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 10, 26)) +>s[0].sub.under["shape"].radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 10, 26)) +>s[0].sub.under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>s[0].sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) +>sub : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>"shape" : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>radius : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 10, 26)) +>s[0]["sub"].under.shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>s[0]["sub"].under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>s : Symbol(s, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 30, 17)) +>0 : Symbol(Subshape["0"], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 14, 20)) +>"sub" : Symbol(sub, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 15, 10)) +>under : Symbol(under, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 16, 14)) +>shape : Symbol(shape, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 17, 20)) +>"radius" : Symbol(Circle.radius, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 10, 26)) } } interface X { ->X : Symbol(X, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 36, 1)) +>X : Symbol(X, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 36, 1)) 0: "xx", ->0 : Symbol(X[0], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 38, 13)) +>0 : Symbol(X[0], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 38, 13)) 1: number ->1 : Symbol(X[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 39, 12)) +>1 : Symbol(X[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 39, 12)) } interface Y { ->Y : Symbol(Y, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 41, 1)) +>Y : Symbol(Y, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 41, 1)) 0: "yy", ->0 : Symbol(Y[0], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 43, 13)) +>0 : Symbol(Y[0], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 43, 13)) 1: string ->1 : Symbol(Y[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 44, 12)) +>1 : Symbol(Y[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 44, 12)) } type A = ["aa", number]; ->A : Symbol(A, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 46, 1)) +>A : Symbol(A, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 46, 1)) type B = ["bb", string]; ->B : Symbol(B, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 48, 24)) +>B : Symbol(B, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 48, 24)) type Z = X | Y; ->Z : Symbol(Z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 49, 24)) ->X : Symbol(X, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 36, 1)) ->Y : Symbol(Y, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 41, 1)) +>Z : Symbol(Z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 49, 24)) +>X : Symbol(X, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 36, 1)) +>Y : Symbol(Y, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 41, 1)) type C = A | B; ->C : Symbol(C, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 51, 15)) ->A : Symbol(A, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 46, 1)) ->B : Symbol(B, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 48, 24)) +>C : Symbol(C, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 51, 15)) +>A : Symbol(A, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 46, 1)) +>B : Symbol(B, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 48, 24)) function check(z: Z, c: C) { ->check : Symbol(check, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 53, 15)) ->z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 15)) ->Z : Symbol(Z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 49, 24)) ->c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 20)) ->C : Symbol(C, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 51, 15)) +>check : Symbol(check, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 53, 15)) +>z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 15)) +>Z : Symbol(Z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 49, 24)) +>c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 20)) +>C : Symbol(C, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 51, 15)) z[0] // fine, typescript sees "xx" | "yy" ->z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 15)) ->0 : Symbol(0, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 38, 13), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 43, 13)) +>z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 15)) +>0 : Symbol(0, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 38, 13), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 43, 13)) switch (z[0]) { ->z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 15)) ->0 : Symbol(0, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 38, 13), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 43, 13)) +>z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 15)) +>0 : Symbol(0, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 38, 13), Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 43, 13)) case "xx": var xx: number = z[1] // should be number ->xx : Symbol(xx, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 59, 15)) ->z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 15)) ->1 : Symbol(X[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 39, 12)) +>xx : Symbol(xx, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 59, 15)) +>z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 15)) +>1 : Symbol(X[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 39, 12)) break; case "yy": var yy: string = z[1] // should be string ->yy : Symbol(yy, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 62, 15)) ->z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 15)) ->1 : Symbol(Y[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 44, 12)) +>yy : Symbol(yy, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 62, 15)) +>z : Symbol(z, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 15)) +>1 : Symbol(Y[1], Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 44, 12)) break; } c[0] // fine, typescript sees "xx" | "yy" ->c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 20)) +>c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 20)) >0 : Symbol(0) switch (c[0]) { ->c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 20)) +>c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 20)) >0 : Symbol(0) case "aa": var aa: number = c[1] // should be number ->aa : Symbol(aa, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 68, 15)) ->c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 20)) +>aa : Symbol(aa, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 68, 15)) +>c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 20)) >1 : Symbol(1) break; case "bb": var bb: string = c[1] // should be string ->bb : Symbol(bb, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 71, 15)) ->c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 55, 20)) +>bb : Symbol(bb, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 71, 15)) +>c : Symbol(c, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 55, 20)) >1 : Symbol(1) break; @@ -256,13 +256,13 @@ function check(z: Z, c: C) { } export function g(pair: [number, string?]): string { ->g : Symbol(g, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 74, 1)) ->pair : Symbol(pair, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 76, 18)) +>g : Symbol(g, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 74, 1)) +>pair : Symbol(pair, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 76, 18)) return pair[1] ? pair[1] : 'nope'; ->pair : Symbol(pair, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 76, 18)) +>pair : Symbol(pair, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 76, 18)) >1 : Symbol(1) ->pair : Symbol(pair, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty.ts, 76, 18)) +>pair : Symbol(pair, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty1.ts, 76, 18)) >1 : Symbol(1) } diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.types b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.types similarity index 95% rename from tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.types rename to tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.types index f88376b118fb0..ee4fc6c2ec9c8 100644 --- a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty.types +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty1.types @@ -1,4 +1,4 @@ -=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty.ts === +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty1.ts === interface Square { ["dash-ok"]: "square"; >["dash-ok"] : "square" diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.js b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.js new file mode 100644 index 0000000000000..1c539d280e132 --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.js @@ -0,0 +1,18 @@ +//// [typeGuardNarrowsIndexedAccessOfKnownProperty2.ts] +const foo: { key?: number } = {}; +const key = 'key' as const; + +if (foo[key]) { + foo[key]; // number + foo.key; // number +} + + +//// [typeGuardNarrowsIndexedAccessOfKnownProperty2.js] +"use strict"; +var foo = {}; +var key = 'key'; +if (foo[key]) { + foo[key]; // number + foo.key; // number +} diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.symbols b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.symbols new file mode 100644 index 0000000000000..b0ac52f071476 --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty2.ts === +const foo: { key?: number } = {}; +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 0, 5)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 0, 12)) + +const key = 'key' as const; +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 1, 5)) +>const : Symbol(const) + +if (foo[key]) { +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 0, 5)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 1, 5)) + + foo[key]; // number +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 0, 5)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 1, 5)) + + foo.key; // number +>foo.key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 0, 12)) +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 0, 5)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty2.ts, 0, 12)) +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.types b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.types new file mode 100644 index 0000000000000..656540534e4f6 --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty2.types @@ -0,0 +1,27 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty2.ts === +const foo: { key?: number } = {}; +>foo : { key?: number | undefined; } +>key : number | undefined +>{} : {} + +const key = 'key' as const; +>key : "key" +>'key' as const : "key" +>'key' : "key" + +if (foo[key]) { +>foo[key] : number | undefined +>foo : { key?: number | undefined; } +>key : "key" + + foo[key]; // number +>foo[key] : number +>foo : { key?: number | undefined; } +>key : "key" + + foo.key; // number +>foo.key : number +>foo : { key?: number | undefined; } +>key : number +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.js b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.js new file mode 100644 index 0000000000000..cae5cb742ab2e --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.js @@ -0,0 +1,18 @@ +//// [typeGuardNarrowsIndexedAccessOfKnownProperty3.ts] +type Foo = (number | undefined)[] | undefined; + +const foo: Foo = [1, 2, 3]; +const index = 1; + +if (foo !== undefined && foo[index] !== undefined && foo[index] >= 0) { + foo[index] // number +} + + +//// [typeGuardNarrowsIndexedAccessOfKnownProperty3.js] +"use strict"; +var foo = [1, 2, 3]; +var index = 1; +if (foo !== undefined && foo[index] !== undefined && foo[index] >= 0) { + foo[index]; // number +} diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.symbols b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.symbols new file mode 100644 index 0000000000000..06506802bdf2a --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.symbols @@ -0,0 +1,25 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty3.ts === +type Foo = (number | undefined)[] | undefined; +>Foo : Symbol(Foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 0, 0)) + +const foo: Foo = [1, 2, 3]; +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 2, 5)) +>Foo : Symbol(Foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 0, 0)) + +const index = 1; +>index : Symbol(index, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 3, 5)) + +if (foo !== undefined && foo[index] !== undefined && foo[index] >= 0) { +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 2, 5)) +>undefined : Symbol(undefined) +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 2, 5)) +>index : Symbol(index, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 3, 5)) +>undefined : Symbol(undefined) +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 2, 5)) +>index : Symbol(index, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 3, 5)) + + foo[index] // number +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 2, 5)) +>index : Symbol(index, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty3.ts, 3, 5)) +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.types b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.types new file mode 100644 index 0000000000000..b4c751d074398 --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty3.types @@ -0,0 +1,38 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty3.ts === +type Foo = (number | undefined)[] | undefined; +>Foo : Foo + +const foo: Foo = [1, 2, 3]; +>foo : Foo +>[1, 2, 3] : number[] +>1 : 1 +>2 : 2 +>3 : 3 + +const index = 1; +>index : 1 +>1 : 1 + +if (foo !== undefined && foo[index] !== undefined && foo[index] >= 0) { +>foo !== undefined && foo[index] !== undefined && foo[index] >= 0 : boolean +>foo !== undefined && foo[index] !== undefined : boolean +>foo !== undefined : boolean +>foo : (number | undefined)[] +>undefined : undefined +>foo[index] !== undefined : boolean +>foo[index] : number | undefined +>foo : (number | undefined)[] +>index : 1 +>undefined : undefined +>foo[index] >= 0 : boolean +>foo[index] : number +>foo : (number | undefined)[] +>index : 1 +>0 : 0 + + foo[index] // number +>foo[index] : number +>foo : (number | undefined)[] +>index : 1 +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.js b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.js new file mode 100644 index 0000000000000..dc5cd0c688c87 --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.js @@ -0,0 +1,20 @@ +//// [typeGuardNarrowsIndexedAccessOfKnownProperty4.ts] +const foo: Record = { a: undefined, b: "string" } +for (let key of ["a", "b", "c"]) { + if (foo[key]) { + foo[key] // string + foo[key].length + } +} + + +//// [typeGuardNarrowsIndexedAccessOfKnownProperty4.js] +"use strict"; +var foo = { a: undefined, b: "string" }; +for (var _i = 0, _a = ["a", "b", "c"]; _i < _a.length; _i++) { + var key = _a[_i]; + if (foo[key]) { + foo[key]; // string + foo[key].length; + } +} diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.symbols b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.symbols new file mode 100644 index 0000000000000..d3b10202046a8 --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty4.ts === +const foo: Record = { a: undefined, b: "string" } +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 0, 5)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 0, 49)) +>undefined : Symbol(undefined) +>b : Symbol(b, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 0, 63)) + +for (let key of ["a", "b", "c"]) { +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 1, 8)) + + if (foo[key]) { +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 0, 5)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 1, 8)) + + foo[key] // string +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 0, 5)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 1, 8)) + + foo[key].length +>foo[key].length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>foo : Symbol(foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 0, 5)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty4.ts, 1, 8)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + } +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.types b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.types new file mode 100644 index 0000000000000..1b58d41a6a14d --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty4.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty4.ts === +const foo: Record = { a: undefined, b: "string" } +>foo : Record +>{ a: undefined, b: "string" } : { a: undefined; b: string; } +>a : undefined +>undefined : undefined +>b : string +>"string" : "string" + +for (let key of ["a", "b", "c"]) { +>key : string +>["a", "b", "c"] : string[] +>"a" : "a" +>"b" : "b" +>"c" : "c" + + if (foo[key]) { +>foo[key] : string | undefined +>foo : Record +>key : string + + foo[key] // string +>foo[key] : string +>foo : Record +>key : string + + foo[key].length +>foo[key].length : number +>foo[key] : string +>foo : Record +>key : string +>length : number + } +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.js b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.js new file mode 100644 index 0000000000000..4afdfe9f7b0ee --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.js @@ -0,0 +1,28 @@ +//// [typeGuardNarrowsIndexedAccessOfKnownProperty5.ts] +class Foo { + x: number | undefined; + + constructor() { + this.x = 5; + + this.x; // number + this['x']; // number + + const key = 'x'; + this[key]; // number + } +} + + +//// [typeGuardNarrowsIndexedAccessOfKnownProperty5.js] +"use strict"; +var Foo = /** @class */ (function () { + function Foo() { + this.x = 5; + this.x; // number + this['x']; // number + var key = 'x'; + this[key]; // number + } + return Foo; +}()); diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.symbols b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.symbols new file mode 100644 index 0000000000000..cf549608a768f --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty5.ts === +class Foo { +>Foo : Symbol(Foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 0)) + + x: number | undefined; +>x : Symbol(Foo.x, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 11)) + + constructor() { + this.x = 5; +>this.x : Symbol(Foo.x, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 11)) +>this : Symbol(Foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 0)) +>x : Symbol(Foo.x, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 11)) + + this.x; // number +>this.x : Symbol(Foo.x, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 11)) +>this : Symbol(Foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 0)) +>x : Symbol(Foo.x, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 11)) + + this['x']; // number +>this : Symbol(Foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 0)) +>'x' : Symbol(Foo.x, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 11)) + + const key = 'x'; +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 9, 13)) + + this[key]; // number +>this : Symbol(Foo, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 0, 0)) +>key : Symbol(key, Decl(typeGuardNarrowsIndexedAccessOfKnownProperty5.ts, 9, 13)) + } +} + diff --git a/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.types b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.types new file mode 100644 index 0000000000000..2d948a2c277b7 --- /dev/null +++ b/tests/baselines/reference/typeGuardNarrowsIndexedAccessOfKnownProperty5.types @@ -0,0 +1,36 @@ +=== tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty5.ts === +class Foo { +>Foo : Foo + + x: number | undefined; +>x : number | undefined + + constructor() { + this.x = 5; +>this.x = 5 : 5 +>this.x : number | undefined +>this : this +>x : number | undefined +>5 : 5 + + this.x; // number +>this.x : number +>this : this +>x : number + + this['x']; // number +>this['x'] : number +>this : this +>'x' : "x" + + const key = 'x'; +>key : "x" +>'x' : "x" + + this[key]; // number +>this[key] : number +>this : this +>key : "x" + } +} + diff --git a/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty.ts b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty1.ts similarity index 100% rename from tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty.ts rename to tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty1.ts diff --git a/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty2.ts b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty2.ts new file mode 100644 index 0000000000000..2dd12edde864e --- /dev/null +++ b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty2.ts @@ -0,0 +1,9 @@ +// @strict: true + +const foo: { key?: number } = {}; +const key = 'key' as const; + +if (foo[key]) { + foo[key]; // number + foo.key; // number +} diff --git a/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty3.ts b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty3.ts new file mode 100644 index 0000000000000..7b92297fb48c5 --- /dev/null +++ b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty3.ts @@ -0,0 +1,10 @@ +// @strict: true + +type Foo = (number | undefined)[] | undefined; + +const foo: Foo = [1, 2, 3]; +const index = 1; + +if (foo !== undefined && foo[index] !== undefined && foo[index] >= 0) { + foo[index] // number +} diff --git a/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty4.ts b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty4.ts new file mode 100644 index 0000000000000..19b52b63fc006 --- /dev/null +++ b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty4.ts @@ -0,0 +1,9 @@ +// @strict: true + +const foo: Record = { a: undefined, b: "string" } +for (let key of ["a", "b", "c"]) { + if (foo[key]) { + foo[key] // string + foo[key].length + } +} diff --git a/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty5.ts b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty5.ts new file mode 100644 index 0000000000000..aa2782c493268 --- /dev/null +++ b/tests/cases/compiler/typeGuardNarrowsIndexedAccessOfKnownProperty5.ts @@ -0,0 +1,15 @@ +// @strict: true + +class Foo { + x: number | undefined; + + constructor() { + this.x = 5; + + this.x; // number + this['x']; // number + + const key = 'x'; + this[key]; // number + } +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts index 7b0da5059b30a..3caf731626494 100644 --- a/tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/strictPropertyInitialization.ts @@ -1,5 +1,5 @@ // @strict: true -// @target:es2015 +// @target: es2015 // @declaration: true // Properties with non-undefined types require initialization @@ -135,3 +135,18 @@ class C11 { this.#b = someValue(); } } + +const a = 'a'; +const b = Symbol(); + +class C12 { + [a]: number; + [b]: number; + ['c']: number; + + constructor() { + this[a] = 1; + this[b] = 1; + this['c'] = 1; + } +}