From 554be1fc0e733545258584168a0cbf39ad6b0cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 3 Nov 2024 13:02:24 +0100 Subject: [PATCH 1/8] Use contextual type of the left operand for the right one in assignments to auto-typed class fields --- src/compiler/checker.ts | 18 ++- ...alizationInferenceWithElementAccess1.types | 12 +- ...tualTypingOutsideOfConstructor1.errors.txt | 43 +++++ ...textualTypingOutsideOfConstructor1.symbols | 83 ++++++++++ ...ontextualTypingOutsideOfConstructor1.types | 151 ++++++++++++++++++ .../classAttributeInferenceTemplate.js | 24 +-- .../classAttributeInferenceTemplate.symbols | 12 +- .../classAttributeInferenceTemplate.types | 40 +++-- .../classAttributeInferenceTemplateJS.symbols | 12 +- .../classAttributeInferenceTemplateJS.types | 40 +++-- ...lassAttributeInferenceUncheckedJs1.symbols | 36 +++++ .../classAttributeInferenceUncheckedJs1.types | 49 ++++++ ...ializationInferenceWithElementAccess.types | 12 +- ...tualTypingOutsideOfStaticBlock1.errors.txt | 41 +++++ ...textualTypingOutsideOfStaticBlock1.symbols | 81 ++++++++++ ...ontextualTypingOutsideOfStaticBlock1.types | 149 +++++++++++++++++ .../reference/controlFlowAutoAccessor1.types | 32 ++-- .../controlFlowPrivateClassField.types | 6 +- .../genericSetterInClassTypeJsDoc.types | 3 +- .../privateNameUncheckedJsOptionalChain.types | 4 +- ...ceContextualTypingOutsideOfConstructor1.ts | 35 ++++ .../classAttributeInferenceTemplate.ts | 12 +- .../classAttributeInferenceTemplateJS.ts | 12 +- .../classAttributeInferenceUncheckedJs1.ts | 21 +++ ...ceContextualTypingOutsideOfStaticBlock1.ts | 33 ++++ 25 files changed, 837 insertions(+), 124 deletions(-) create mode 100644 tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt create mode 100644 tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols create mode 100644 tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types create mode 100644 tests/baselines/reference/classAttributeInferenceUncheckedJs1.symbols create mode 100644 tests/baselines/reference/classAttributeInferenceUncheckedJs1.types create mode 100644 tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt create mode 100644 tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols create mode 100644 tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types create mode 100644 tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts create mode 100644 tests/cases/compiler/classAttributeInferenceUncheckedJs1.ts create mode 100644 tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce0291367b510..75513ab81ac70 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31448,8 +31448,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const lhsSymbol = getSymbolForExpression(binaryExpression.left); const decl = lhsSymbol && lhsSymbol.valueDeclaration; // Unannotated, uninitialized property declarations have a type implied by their usage in the constructor. - // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case. - if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl))) { + // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case when the assignment declaration is in the constructor + if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl)) && (!isAccessExpression(binaryExpression.left) || isThisPropertyAccessInConstructor(binaryExpression.left, lhsSymbol))) { const overallAnnotation = getEffectiveTypeAnnotationNode(decl); return (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) || (isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) : undefined); @@ -34010,8 +34010,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isThisPropertyAccessInConstructor(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) { - return (isConstructorDeclaredProperty(prop) || isThisProperty(node) && isAutoTypedProperty(prop)) - && getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false) === getDeclaringConstructor(prop); + if (!isConstructorDeclaredProperty(prop) && (!isThisProperty(node) || !isAutoTypedProperty(prop))) { + return false; + } + const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); + if (thisContainer === getDeclaringConstructor(prop)) { + return true; + } + const classLikeDeclaration = prop.parent && getClassLikeDeclarationOfSymbol(prop.parent); + if (!classLikeDeclaration) { + return false; + } + return thisContainer === findConstructorDeclaration(classLikeDeclaration); } function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined, writeOnly?: boolean) { diff --git a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types index 63ed461d086ca..17aab43cccb26 100644 --- a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types +++ b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types @@ -28,8 +28,7 @@ export class Cls { this['x'] = [seed]; >this['x'] = [seed] : number[] > : ^^^^^^^^ ->this['x'] : number[] -> : ^^^^^^^^ +>this['x'] : any >this : this > : ^^^^ >'x' : "x" @@ -42,8 +41,7 @@ export class Cls { this['y'] = { seed }; >this['y'] = { seed } : { seed: number; } > : ^^^^^^^^^^^^^^^^^ ->this['y'] : { seed: number; } -> : ^^^^^^^^^^^^^^^^^ +>this['y'] : any >this : this > : ^^^^ >'y' : "y" @@ -56,8 +54,7 @@ export class Cls { this['z'] = `${seed}`; >this['z'] = `${seed}` : string > : ^^^^^^ ->this['z'] : string -> : ^^^^^^ +>this['z'] : any >this : this > : ^^^^ >'z' : "z" @@ -70,8 +67,7 @@ export class Cls { this[0] = [seed]; >this[0] = [seed] : number[] > : ^^^^^^^^ ->this[0] : number[] -> : ^^^^^^^^ +>this[0] : any >this : this > : ^^^^ >0 : 0 diff --git a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt new file mode 100644 index 0000000000000..24c4793121ee2 --- /dev/null +++ b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt @@ -0,0 +1,43 @@ +classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(16,20): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(29,20): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? + + +==== classAttributeInferenceContextualTypingOutsideOfConstructor1.ts (2 errors) ==== + // https://github.com/microsoft/TypeScript/issues/60394 + + type State = { type: "running"; speed: number } | { type: "stopped" }; + + declare const initialState: State; + + class Actor1 { + private state; + + constructor() { + this.state = initialState; + } + + run(speed: number) { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classAttributeInferenceContextualTypingOutsideOfConstructor1.ts:3:16: The expected type comes from property 'type' which is declared here on type 'State' + } + } + + class Actor2 { + accessor state; + + constructor() { + this.state = initialState; + } + + run(speed: number) { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classAttributeInferenceContextualTypingOutsideOfConstructor1.ts:3:16: The expected type comes from property 'type' which is declared here on type 'State' + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols new file mode 100644 index 0000000000000..5c21d3a3caa33 --- /dev/null +++ b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols @@ -0,0 +1,83 @@ +//// [tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts] //// + +=== classAttributeInferenceContextualTypingOutsideOfConstructor1.ts === +// https://github.com/microsoft/TypeScript/issues/60394 + +type State = { type: "running"; speed: number } | { type: "stopped" }; +>State : Symbol(State, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 0, 0)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 2, 14)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 2, 31)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 2, 51)) + +declare const initialState: State; +>initialState : Symbol(initialState, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 13)) +>State : Symbol(State, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 0, 0)) + +class Actor1 { +>Actor1 : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) + + private state; +>state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) + + constructor() { + this.state = initialState; +>this.state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) +>state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>initialState : Symbol(initialState, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 13)) + } + + run(speed: number) { +>run : Symbol(Actor1.run, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 11, 3)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 13, 6)) + + this.state = { type: "running", speed }; +>this.state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) +>state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 14, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 14, 35)) + + this.state = { type: "runnnning", speed }; // error +>this.state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) +>state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 15, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 15, 37)) + } +} + +class Actor2 { +>Actor2 : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) + + accessor state; +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) + + constructor() { + this.state = initialState; +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>initialState : Symbol(initialState, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 13)) + } + + run(speed: number) { +>run : Symbol(Actor2.run, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 3)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 26, 6)) + + this.state = { type: "running", speed }; +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 27, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 27, 35)) + + this.state = { type: "runnnning", speed }; // error +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 28, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 28, 37)) + } +} + diff --git a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types new file mode 100644 index 0000000000000..b57e0c2dc17f3 --- /dev/null +++ b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types @@ -0,0 +1,151 @@ +//// [tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts] //// + +=== classAttributeInferenceContextualTypingOutsideOfConstructor1.ts === +// https://github.com/microsoft/TypeScript/issues/60394 + +type State = { type: "running"; speed: number } | { type: "stopped" }; +>State : State +> : ^^^^^ +>type : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ +>type : "stopped" +> : ^^^^^^^^^ + +declare const initialState: State; +>initialState : State +> : ^^^^^ + +class Actor1 { +>Actor1 : Actor1 +> : ^^^^^^ + + private state; +>state : State +> : ^^^^^ + + constructor() { + this.state = initialState; +>this.state = initialState : State +> : ^^^^^ +>this.state : any +> : ^^^ +>this : this +> : ^^^^ +>state : any +> : ^^^ +>initialState : State +> : ^^^^^ + } + + run(speed: number) { +>run : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "running", speed }; +>this.state = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "runnnning", speed }; // error +>this.state = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } +} + +class Actor2 { +>Actor2 : Actor2 +> : ^^^^^^ + + accessor state; +>state : State +> : ^^^^^ + + constructor() { + this.state = initialState; +>this.state = initialState : State +> : ^^^^^ +>this.state : any +> : ^^^ +>this : this +> : ^^^^ +>state : any +> : ^^^ +>initialState : State +> : ^^^^^ + } + + run(speed: number) { +>run : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "running", speed }; +>this.state = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "runnnning", speed }; // error +>this.state = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } +} + diff --git a/tests/baselines/reference/classAttributeInferenceTemplate.js b/tests/baselines/reference/classAttributeInferenceTemplate.js index 60da0b173d391..92ecb3ba27560 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplate.js +++ b/tests/baselines/reference/classAttributeInferenceTemplate.js @@ -8,10 +8,10 @@ class MyClass { constructor() { const variable = 'something' - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error + this.property = `foo`; + this.property2 = `foo-${variable}`; - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; } } @@ -22,10 +22,10 @@ class MyClass2 { constructor() { const variable = 'something' - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error + this.property = `foo`; + this.property2 = `foo-${variable}`; - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; } } @@ -37,9 +37,9 @@ class MyClass { property2; constructor() { const variable = 'something'; - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; } } class MyClass2 { @@ -47,8 +47,8 @@ class MyClass2 { accessor property2; constructor() { const variable = 'something'; - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; } } diff --git a/tests/baselines/reference/classAttributeInferenceTemplate.symbols b/tests/baselines/reference/classAttributeInferenceTemplate.symbols index a5b2df3334bfc..5dd5d39fbcd14 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplate.symbols +++ b/tests/baselines/reference/classAttributeInferenceTemplate.symbols @@ -14,18 +14,18 @@ class MyClass { const variable = 'something' >variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 5, 13)) - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property : Symbol(MyClass.property, Decl(classAttributeInferenceTemplate.ts, 0, 15)) >this : Symbol(MyClass, Decl(classAttributeInferenceTemplate.ts, 0, 0)) >property : Symbol(MyClass.property, Decl(classAttributeInferenceTemplate.ts, 0, 15)) - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 : Symbol(MyClass.property2, Decl(classAttributeInferenceTemplate.ts, 1, 13)) >this : Symbol(MyClass, Decl(classAttributeInferenceTemplate.ts, 0, 0)) >property2 : Symbol(MyClass.property2, Decl(classAttributeInferenceTemplate.ts, 1, 13)) >variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 5, 13)) - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : Symbol(localProperty, Decl(classAttributeInferenceTemplate.ts, 10, 13)) >variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 5, 13)) } @@ -44,18 +44,18 @@ class MyClass2 { const variable = 'something' >variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 19, 13)) - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property : Symbol(MyClass2.property, Decl(classAttributeInferenceTemplate.ts, 14, 16)) >this : Symbol(MyClass2, Decl(classAttributeInferenceTemplate.ts, 12, 1)) >property : Symbol(MyClass2.property, Decl(classAttributeInferenceTemplate.ts, 14, 16)) - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 : Symbol(MyClass2.property2, Decl(classAttributeInferenceTemplate.ts, 15, 22)) >this : Symbol(MyClass2, Decl(classAttributeInferenceTemplate.ts, 12, 1)) >property2 : Symbol(MyClass2.property2, Decl(classAttributeInferenceTemplate.ts, 15, 22)) >variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 19, 13)) - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : Symbol(localProperty, Decl(classAttributeInferenceTemplate.ts, 24, 13)) >variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 19, 13)) } diff --git a/tests/baselines/reference/classAttributeInferenceTemplate.types b/tests/baselines/reference/classAttributeInferenceTemplate.types index 1386ee62d417a..cf407312918af 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplate.types +++ b/tests/baselines/reference/classAttributeInferenceTemplate.types @@ -20,33 +20,31 @@ class MyClass { >'something' : "something" > : ^^^^^^^^^^^ - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : string -> : ^^^^^^ +>this.property : any >this : this > : ^^^^ ->property : string -> : ^^^^^^ +>property : any +> : ^^^ >`foo` : "foo" > : ^^^^^ - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : string -> : ^^^^^^ +>this.property2 : any >this : this > : ^^^^ ->property2 : string -> : ^^^^^^ +>property2 : any +> : ^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" > : ^^^^^^^^^^^ - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : "foo-something" > : ^^^^^^^^^^^^^^^ >`foo-${variable}` : "foo-something" @@ -75,33 +73,31 @@ class MyClass2 { >'something' : "something" > : ^^^^^^^^^^^ - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : string -> : ^^^^^^ +>this.property : any >this : this > : ^^^^ ->property : string -> : ^^^^^^ +>property : any +> : ^^^ >`foo` : "foo" > : ^^^^^ - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : string -> : ^^^^^^ +>this.property2 : any >this : this > : ^^^^ ->property2 : string -> : ^^^^^^ +>property2 : any +> : ^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" > : ^^^^^^^^^^^ - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : "foo-something" > : ^^^^^^^^^^^^^^^ >`foo-${variable}` : "foo-something" diff --git a/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols b/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols index 96e45c51a750a..c7b17f892a942 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols +++ b/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols @@ -14,18 +14,18 @@ class MyClass { const variable = 'something' >variable : Symbol(variable, Decl(index.js, 5, 13)) - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property : Symbol(MyClass.property, Decl(index.js, 0, 15)) >this : Symbol(MyClass, Decl(index.js, 0, 0)) >property : Symbol(MyClass.property, Decl(index.js, 0, 15)) - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 : Symbol(MyClass.property2, Decl(index.js, 1, 13)) >this : Symbol(MyClass, Decl(index.js, 0, 0)) >property2 : Symbol(MyClass.property2, Decl(index.js, 1, 13)) >variable : Symbol(variable, Decl(index.js, 5, 13)) - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : Symbol(localProperty, Decl(index.js, 10, 13)) >variable : Symbol(variable, Decl(index.js, 5, 13)) } @@ -44,18 +44,18 @@ class MyClass2 { const variable = 'something' >variable : Symbol(variable, Decl(index.js, 19, 13)) - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property : Symbol(MyClass2.property, Decl(index.js, 14, 16)) >this : Symbol(MyClass2, Decl(index.js, 12, 1)) >property : Symbol(MyClass2.property, Decl(index.js, 14, 16)) - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 : Symbol(MyClass2.property2, Decl(index.js, 15, 22)) >this : Symbol(MyClass2, Decl(index.js, 12, 1)) >property2 : Symbol(MyClass2.property2, Decl(index.js, 15, 22)) >variable : Symbol(variable, Decl(index.js, 19, 13)) - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : Symbol(localProperty, Decl(index.js, 24, 13)) >variable : Symbol(variable, Decl(index.js, 19, 13)) } diff --git a/tests/baselines/reference/classAttributeInferenceTemplateJS.types b/tests/baselines/reference/classAttributeInferenceTemplateJS.types index 74d16a8c1409d..f2934c31b6605 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplateJS.types +++ b/tests/baselines/reference/classAttributeInferenceTemplateJS.types @@ -20,33 +20,31 @@ class MyClass { >'something' : "something" > : ^^^^^^^^^^^ - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : string -> : ^^^^^^ +>this.property : any >this : this > : ^^^^ ->property : string -> : ^^^^^^ +>property : any +> : ^^^ >`foo` : "foo" > : ^^^^^ - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : string -> : ^^^^^^ +>this.property2 : any >this : this > : ^^^^ ->property2 : string -> : ^^^^^^ +>property2 : any +> : ^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" > : ^^^^^^^^^^^ - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : "foo-something" > : ^^^^^^^^^^^^^^^ >`foo-${variable}` : "foo-something" @@ -75,33 +73,31 @@ class MyClass2 { >'something' : "something" > : ^^^^^^^^^^^ - this.property = `foo`; // Correctly inferred as `string` + this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : string -> : ^^^^^^ +>this.property : any >this : this > : ^^^^ ->property : string -> : ^^^^^^ +>property : any +> : ^^^ >`foo` : "foo" > : ^^^^^ - this.property2 = `foo-${variable}`; // Causes an error + this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : string -> : ^^^^^^ +>this.property2 : any >this : this > : ^^^^ ->property2 : string -> : ^^^^^^ +>property2 : any +> : ^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" > : ^^^^^^^^^^^ - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; >localProperty : "foo-something" > : ^^^^^^^^^^^^^^^ >`foo-${variable}` : "foo-something" diff --git a/tests/baselines/reference/classAttributeInferenceUncheckedJs1.symbols b/tests/baselines/reference/classAttributeInferenceUncheckedJs1.symbols new file mode 100644 index 0000000000000..79fa1efb0466c --- /dev/null +++ b/tests/baselines/reference/classAttributeInferenceUncheckedJs1.symbols @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/classAttributeInferenceUncheckedJs1.ts] //// + +=== classAttributeInferenceUncheckedJs1.js === +class C1 { +>C1 : Symbol(C1, Decl(classAttributeInferenceUncheckedJs1.js, 0, 0)) + + bar; +>bar : Symbol(C1.bar, Decl(classAttributeInferenceUncheckedJs1.js, 0, 10)) + + constructor () { + this.foo; +>this : Symbol(C1, Decl(classAttributeInferenceUncheckedJs1.js, 0, 0)) + + this.bar; +>this.bar : Symbol(C1.bar, Decl(classAttributeInferenceUncheckedJs1.js, 0, 10)) +>this : Symbol(C1, Decl(classAttributeInferenceUncheckedJs1.js, 0, 0)) +>bar : Symbol(C1.bar, Decl(classAttributeInferenceUncheckedJs1.js, 0, 10)) + } +} + +class C2 { +>C2 : Symbol(C2, Decl(classAttributeInferenceUncheckedJs1.js, 6, 1)) + + #bar; +>#bar : Symbol(C2.#bar, Decl(classAttributeInferenceUncheckedJs1.js, 8, 10)) + + constructor () { + this.#foo; +>this : Symbol(C2, Decl(classAttributeInferenceUncheckedJs1.js, 6, 1)) + + this.#bar; +>this.#bar : Symbol(C2.#bar, Decl(classAttributeInferenceUncheckedJs1.js, 8, 10)) +>this : Symbol(C2, Decl(classAttributeInferenceUncheckedJs1.js, 6, 1)) + } +} + diff --git a/tests/baselines/reference/classAttributeInferenceUncheckedJs1.types b/tests/baselines/reference/classAttributeInferenceUncheckedJs1.types new file mode 100644 index 0000000000000..ea81b20d9d6ff --- /dev/null +++ b/tests/baselines/reference/classAttributeInferenceUncheckedJs1.types @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/classAttributeInferenceUncheckedJs1.ts] //// + +=== classAttributeInferenceUncheckedJs1.js === +class C1 { +>C1 : C1 +> : ^^ + + bar; +>bar : any + + constructor () { + this.foo; +>this.foo : error +>this : this +> : ^^^^ +>foo : any +> : ^^^ + + this.bar; +>this.bar : undefined +> : ^^^^^^^^^ +>this : this +> : ^^^^ +>bar : undefined +> : ^^^^^^^^^ + } +} + +class C2 { +>C2 : C2 +> : ^^ + + #bar; +>#bar : any + + constructor () { + this.#foo; +>this.#foo : error +>this : this +> : ^^^^ + + this.#bar; +>this.#bar : undefined +> : ^^^^^^^^^ +>this : this +> : ^^^^ + } +} + diff --git a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types index a0a173712e93d..013ed75e2245e 100644 --- a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types +++ b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types @@ -29,8 +29,7 @@ export class Cls { this['x'] = [seed]; >this['x'] = [seed] : number[] > : ^^^^^^^^ ->this['x'] : number[] -> : ^^^^^^^^ +>this['x'] : any >this : this > : ^^^^ >'x' : "x" @@ -43,8 +42,7 @@ export class Cls { this['y'] = { seed }; >this['y'] = { seed } : { seed: number; } > : ^^^^^^^^^^^^^^^^^ ->this['y'] : { seed: number; } -> : ^^^^^^^^^^^^^^^^^ +>this['y'] : any >this : this > : ^^^^ >'y' : "y" @@ -57,8 +55,7 @@ export class Cls { this['z'] = `${seed}`; >this['z'] = `${seed}` : string > : ^^^^^^ ->this['z'] : string -> : ^^^^^^ +>this['z'] : any >this : this > : ^^^^ >'z' : "z" @@ -71,8 +68,7 @@ export class Cls { this[0] = [seed]; >this[0] = [seed] : number[] > : ^^^^^^^^ ->this[0] : number[] -> : ^^^^^^^^ +>this[0] : any >this : this > : ^^^^ >0 : 0 diff --git a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt new file mode 100644 index 0000000000000..0a3d38bf568c5 --- /dev/null +++ b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt @@ -0,0 +1,41 @@ +classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(14,27): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(27,27): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? + + +==== classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts (2 errors) ==== + type State = { type: "running"; speed: number } | { type: "stopped" }; + + declare const initialState: State; + + class Actor1 { + static initialState; + + static { + this.initialState = initialState; + } + + static setAsInitiallyRunning(speed: number) { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts:1:16: The expected type comes from property 'type' which is declared here on type 'State' + } + } + + class Actor2 { + static accessor initialState; + + static { + this.initialState = initialState; + } + + static setAsInitiallyRunning(speed: number) { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts:1:16: The expected type comes from property 'type' which is declared here on type 'State' + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols new file mode 100644 index 0000000000000..1a8613c38ba66 --- /dev/null +++ b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols @@ -0,0 +1,81 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts] //// + +=== classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts === +type State = { type: "running"; speed: number } | { type: "stopped" }; +>State : Symbol(State, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 0, 0)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 0, 14)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 0, 31)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 0, 51)) + +declare const initialState: State; +>initialState : Symbol(initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 13)) +>State : Symbol(State, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 0, 0)) + +class Actor1 { +>Actor1 : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) + + static initialState; +>initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) + + static { + this.initialState = initialState; +>this.initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) +>initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>initialState : Symbol(initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 13)) + } + + static setAsInitiallyRunning(speed: number) { +>setAsInitiallyRunning : Symbol(Actor1.setAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 9, 3)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 11, 31)) + + this.initialState = { type: "running", speed }; +>this.initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) +>initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 12, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 12, 42)) + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) +>initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 13, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 13, 44)) + } +} + +class Actor2 { +>Actor2 : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) + + static accessor initialState; +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) + + static { + this.initialState = initialState; +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>initialState : Symbol(initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 13)) + } + + static setAsInitiallyRunning(speed: number) { +>setAsInitiallyRunning : Symbol(Actor2.setAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 3)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 24, 31)) + + this.initialState = { type: "running", speed }; +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 25, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 25, 42)) + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 26, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 26, 44)) + } +} + diff --git a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types new file mode 100644 index 0000000000000..83c2a7b549518 --- /dev/null +++ b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types @@ -0,0 +1,149 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts] //// + +=== classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts === +type State = { type: "running"; speed: number } | { type: "stopped" }; +>State : State +> : ^^^^^ +>type : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ +>type : "stopped" +> : ^^^^^^^^^ + +declare const initialState: State; +>initialState : State +> : ^^^^^ + +class Actor1 { +>Actor1 : Actor1 +> : ^^^^^^ + + static initialState; +>initialState : State +> : ^^^^^ + + static { + this.initialState = initialState; +>this.initialState = initialState : State +> : ^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor1 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>initialState : State +> : ^^^^^ + } + + static setAsInitiallyRunning(speed: number) { +>setAsInitiallyRunning : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "running", speed }; +>this.initialState = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor1 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor1 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } +} + +class Actor2 { +>Actor2 : Actor2 +> : ^^^^^^ + + static accessor initialState; +>initialState : State +> : ^^^^^ + + static { + this.initialState = initialState; +>this.initialState = initialState : State +> : ^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor2 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>initialState : State +> : ^^^^^ + } + + static setAsInitiallyRunning(speed: number) { +>setAsInitiallyRunning : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "running", speed }; +>this.initialState = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor2 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor2 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } +} + diff --git a/tests/baselines/reference/controlFlowAutoAccessor1.types b/tests/baselines/reference/controlFlowAutoAccessor1.types index c4e8c3865f43f..85f456da5d851 100644 --- a/tests/baselines/reference/controlFlowAutoAccessor1.types +++ b/tests/baselines/reference/controlFlowAutoAccessor1.types @@ -16,12 +16,12 @@ class Example { this.test = test; >this.test = test : number > : ^^^^^^ ->this.test : number -> : ^^^^^^ +>this.test : any +> : ^^^ >this : this > : ^^^^ ->test : number -> : ^^^^^^ +>test : any +> : ^^^ >test : number > : ^^^^^^ } @@ -55,12 +55,12 @@ class Example2 { this.test = test; >this.test = test : number | undefined > : ^^^^^^^^^^^^^^^^^^ ->this.test : number | undefined -> : ^^^^^^^^^^^^^^^^^^ +>this.test : any +> : ^^^ >this : this > : ^^^^ ->test : number | undefined -> : ^^^^^^^^^^^^^^^^^^ +>test : any +> : ^^^ >test : number | undefined > : ^^^^^^^^^^^^^^^^^^ } @@ -108,12 +108,12 @@ class Example3 { this.value = n; >this.value = n : number > : ^^^^^^ ->this.value : number | null -> : ^^^^^^^^^^^^^ +>this.value : any +> : ^^^ >this : this > : ^^^^ ->value : number | null -> : ^^^^^^^^^^^^^ +>value : any +> : ^^^ >n : number > : ^^^^^^ @@ -128,12 +128,12 @@ class Example3 { this.value = null; >this.value = null : null > : ^^^^ ->this.value : number | null -> : ^^^^^^^^^^^^^ +>this.value : any +> : ^^^ >this : this > : ^^^^ ->value : number | null -> : ^^^^^^^^^^^^^ +>value : any +> : ^^^ } } } diff --git a/tests/baselines/reference/controlFlowPrivateClassField.types b/tests/baselines/reference/controlFlowPrivateClassField.types index fd2ddbd1e4292..6ab1a52d31a53 100644 --- a/tests/baselines/reference/controlFlowPrivateClassField.types +++ b/tests/baselines/reference/controlFlowPrivateClassField.types @@ -16,8 +16,7 @@ class Example { this.#test = test; >this.#test = test : number > : ^^^^^^ ->this.#test : number -> : ^^^^^^ +>this.#test : any >this : this > : ^^^^ >test : number @@ -51,8 +50,7 @@ class Example2 { this.#test = test; >this.#test = test : number | undefined > : ^^^^^^^^^^^^^^^^^^ ->this.#test : number | undefined -> : ^^^^^^^^^^^^^^^^^^ +>this.#test : any >this : this > : ^^^^ >test : number | undefined diff --git a/tests/baselines/reference/genericSetterInClassTypeJsDoc.types b/tests/baselines/reference/genericSetterInClassTypeJsDoc.types index e128037dd9c02..cea5b12645b85 100644 --- a/tests/baselines/reference/genericSetterInClassTypeJsDoc.types +++ b/tests/baselines/reference/genericSetterInClassTypeJsDoc.types @@ -20,8 +20,7 @@ this.#value = initialValue; >this.#value = initialValue : T > : ^ ->this.#value : T -> : ^ +>this.#value : any >this : this > : ^^^^ >initialValue : T diff --git a/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types b/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types index cea9ea7054bd5..efe6863aa0166 100644 --- a/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types +++ b/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types @@ -17,8 +17,8 @@ class C { > : ^^^^ this?.#bar; ->this?.#bar : any -> : ^^^ +>this?.#bar : undefined +> : ^^^^^^^^^ >this : this > : ^^^^ } diff --git a/tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts b/tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts new file mode 100644 index 0000000000000..c1f570b26410c --- /dev/null +++ b/tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts @@ -0,0 +1,35 @@ +// @strict: true +// @noEmit: true +// @target: esnext + +// https://github.com/microsoft/TypeScript/issues/60394 + +type State = { type: "running"; speed: number } | { type: "stopped" }; + +declare const initialState: State; + +class Actor1 { + private state; + + constructor() { + this.state = initialState; + } + + run(speed: number) { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + } +} + +class Actor2 { + accessor state; + + constructor() { + this.state = initialState; + } + + run(speed: number) { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + } +} diff --git a/tests/cases/compiler/classAttributeInferenceTemplate.ts b/tests/cases/compiler/classAttributeInferenceTemplate.ts index c876482a39c8a..95d084c7084c2 100644 --- a/tests/cases/compiler/classAttributeInferenceTemplate.ts +++ b/tests/cases/compiler/classAttributeInferenceTemplate.ts @@ -7,10 +7,10 @@ class MyClass { constructor() { const variable = 'something' - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error + this.property = `foo`; + this.property2 = `foo-${variable}`; - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; } } @@ -21,9 +21,9 @@ class MyClass2 { constructor() { const variable = 'something' - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error + this.property = `foo`; + this.property2 = `foo-${variable}`; - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; } } diff --git a/tests/cases/compiler/classAttributeInferenceTemplateJS.ts b/tests/cases/compiler/classAttributeInferenceTemplateJS.ts index a35fd951d5480..e18556f631bbd 100644 --- a/tests/cases/compiler/classAttributeInferenceTemplateJS.ts +++ b/tests/cases/compiler/classAttributeInferenceTemplateJS.ts @@ -10,10 +10,10 @@ class MyClass { constructor() { const variable = 'something' - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error + this.property = `foo`; + this.property2 = `foo-${variable}`; - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; } } @@ -24,9 +24,9 @@ class MyClass2 { constructor() { const variable = 'something' - this.property = `foo`; // Correctly inferred as `string` - this.property2 = `foo-${variable}`; // Causes an error + this.property = `foo`; + this.property2 = `foo-${variable}`; - const localProperty = `foo-${variable}`; // Correctly inferred as `string` + const localProperty = `foo-${variable}`; } } diff --git a/tests/cases/compiler/classAttributeInferenceUncheckedJs1.ts b/tests/cases/compiler/classAttributeInferenceUncheckedJs1.ts new file mode 100644 index 0000000000000..95e57d75e8e29 --- /dev/null +++ b/tests/cases/compiler/classAttributeInferenceUncheckedJs1.ts @@ -0,0 +1,21 @@ +// @allowJs: true +// @checkJs: false +// @noEmit: true +// @Filename: classAttributeInferenceUncheckedJs1.js +// @target: es2015 + +class C1 { + bar; + constructor () { + this.foo; + this.bar; + } +} + +class C2 { + #bar; + constructor () { + this.#foo; + this.#bar; + } +} diff --git a/tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts b/tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts new file mode 100644 index 0000000000000..89b1def5c3dd5 --- /dev/null +++ b/tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts @@ -0,0 +1,33 @@ +// @strict: true +// @noEmit: true +// @target: esnext + +type State = { type: "running"; speed: number } | { type: "stopped" }; + +declare const initialState: State; + +class Actor1 { + static initialState; + + static { + this.initialState = initialState; + } + + static setAsInitiallyRunning(speed: number) { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + } +} + +class Actor2 { + static accessor initialState; + + static { + this.initialState = initialState; + } + + static setAsInitiallyRunning(speed: number) { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + } +} From 282d20a98fc3d58c017b66485caeb170a370faa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 4 Nov 2024 11:56:18 +0100 Subject: [PATCH 2/8] fixed spurious circularity errors related to static blocks --- src/compiler/checker.ts | 48 +++-- ...alizationInferenceWithElementAccess1.types | 12 +- ...ontextualTypingOutsideOfConstructor1.types | 16 +- .../classAttributeInferenceTemplate.types | 28 +-- .../classAttributeInferenceTemplateJS.types | 28 +-- .../classAttributeInferenceUncheckedJs1.types | 10 +- ...ializationInferenceWithElementAccess.types | 12 +- ...itializationInferenceWithElementAccess1.js | 82 +++++++++ ...izationInferenceWithElementAccess1.symbols | 79 +++++++++ ...alizationInferenceWithElementAccess1.types | 166 ++++++++++++++++++ .../reference/controlFlowAutoAccessor1.types | 32 ++-- .../controlFlowPrivateClassField.types | 6 +- .../genericSetterInClassTypeJsDoc.types | 3 +- .../privateNameUncheckedJsOptionalChain.types | 4 +- ...itializationInferenceWithElementAccess1.ts | 37 ++++ 15 files changed, 480 insertions(+), 83 deletions(-) create mode 100644 tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js create mode 100644 tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols create mode 100644 tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types create mode 100644 tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 75513ab81ac70..8248a4208d84c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11291,6 +11291,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { !declaration.initializer && (noImplicitAny || isInJSFile(declaration)); } + function isThisPropertyAccessInAutoContainer(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) { + const declaration = Debug.checkDefined(prop.valueDeclaration); + if (hasStaticModifier(declaration)) { + if (!isThisProperty(node) || !isAutoTypedProperty(prop)) { + return false; + } + const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); + if (!isClassStaticBlockDeclaration(thisContainer)) { + return false; + } + return (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent; + } + if (!isConstructorDeclaredProperty(prop) && (!isThisProperty(node) || !isAutoTypedProperty(prop))) { + return false; + } + const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); + if (thisContainer === getDeclaringConstructor(prop)) { + return true; + } + const classLikeDeclaration = prop.parent && getClassLikeDeclarationOfSymbol(prop.parent); + if (!classLikeDeclaration) { + return false; + } + return thisContainer === findConstructorDeclaration(classLikeDeclaration); + } + function getDeclaringConstructor(symbol: Symbol) { if (!symbol.declarations) { return; @@ -18548,7 +18574,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (accessFlags & AccessFlags.CacheSymbol) { getNodeLinks(accessNode!).resolvedSymbol = prop; } - if (isThisPropertyAccessInConstructor(accessExpression, prop)) { + if (isThisPropertyAccessInDeclaringConstructor(accessExpression, prop)) { return autoType; } } @@ -31449,7 +31475,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const decl = lhsSymbol && lhsSymbol.valueDeclaration; // Unannotated, uninitialized property declarations have a type implied by their usage in the constructor. // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case when the assignment declaration is in the constructor - if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl)) && (!isAccessExpression(binaryExpression.left) || isThisPropertyAccessInConstructor(binaryExpression.left, lhsSymbol))) { + if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl)) && (!isAccessExpression(binaryExpression.left) || isThisPropertyAccessInAutoContainer(binaryExpression.left, lhsSymbol))) { const overallAnnotation = getEffectiveTypeAnnotationNode(decl); return (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) || (isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) : undefined); @@ -34009,19 +34035,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function isThisPropertyAccessInConstructor(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) { - if (!isConstructorDeclaredProperty(prop) && (!isThisProperty(node) || !isAutoTypedProperty(prop))) { - return false; - } - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); - if (thisContainer === getDeclaringConstructor(prop)) { - return true; - } - const classLikeDeclaration = prop.parent && getClassLikeDeclarationOfSymbol(prop.parent); - if (!classLikeDeclaration) { - return false; - } - return thisContainer === findConstructorDeclaration(classLikeDeclaration); + function isThisPropertyAccessInDeclaringConstructor(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) { + return (isConstructorDeclaredProperty(prop) || isThisProperty(node) && isAutoTypedProperty(prop)) + && getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false) === getDeclaringConstructor(prop); } function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined, writeOnly?: boolean) { @@ -34139,7 +34155,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorType; } - propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writeOnly || isWriteOnlyAccess(node) ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop); + propType = isThisPropertyAccessInDeclaringConstructor(node, prop) ? autoType : writeOnly || isWriteOnlyAccess(node) ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop); } return getFlowTypeOfAccessExpression(node, prop, propType, right, checkMode); diff --git a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types index 17aab43cccb26..63ed461d086ca 100644 --- a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types +++ b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types @@ -28,7 +28,8 @@ export class Cls { this['x'] = [seed]; >this['x'] = [seed] : number[] > : ^^^^^^^^ ->this['x'] : any +>this['x'] : number[] +> : ^^^^^^^^ >this : this > : ^^^^ >'x' : "x" @@ -41,7 +42,8 @@ export class Cls { this['y'] = { seed }; >this['y'] = { seed } : { seed: number; } > : ^^^^^^^^^^^^^^^^^ ->this['y'] : any +>this['y'] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ >this : this > : ^^^^ >'y' : "y" @@ -54,7 +56,8 @@ export class Cls { this['z'] = `${seed}`; >this['z'] = `${seed}` : string > : ^^^^^^ ->this['z'] : any +>this['z'] : string +> : ^^^^^^ >this : this > : ^^^^ >'z' : "z" @@ -67,7 +70,8 @@ export class Cls { this[0] = [seed]; >this[0] = [seed] : number[] > : ^^^^^^^^ ->this[0] : any +>this[0] : number[] +> : ^^^^^^^^ >this : this > : ^^^^ >0 : 0 diff --git a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types index b57e0c2dc17f3..343b5a56045e6 100644 --- a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types +++ b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types @@ -29,12 +29,12 @@ class Actor1 { this.state = initialState; >this.state = initialState : State > : ^^^^^ ->this.state : any -> : ^^^ +>this.state : State +> : ^^^^^ >this : this > : ^^^^ ->state : any -> : ^^^ +>state : State +> : ^^^^^ >initialState : State > : ^^^^^ } @@ -95,12 +95,12 @@ class Actor2 { this.state = initialState; >this.state = initialState : State > : ^^^^^ ->this.state : any -> : ^^^ +>this.state : State +> : ^^^^^ >this : this > : ^^^^ ->state : any -> : ^^^ +>state : State +> : ^^^^^ >initialState : State > : ^^^^^ } diff --git a/tests/baselines/reference/classAttributeInferenceTemplate.types b/tests/baselines/reference/classAttributeInferenceTemplate.types index cf407312918af..849205039f91a 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplate.types +++ b/tests/baselines/reference/classAttributeInferenceTemplate.types @@ -23,22 +23,24 @@ class MyClass { this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : any +>this.property : string +> : ^^^^^^ >this : this > : ^^^^ ->property : any -> : ^^^ +>property : string +> : ^^^^^^ >`foo` : "foo" > : ^^^^^ this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : any +>this.property2 : string +> : ^^^^^^ >this : this > : ^^^^ ->property2 : any -> : ^^^ +>property2 : string +> : ^^^^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" @@ -76,22 +78,24 @@ class MyClass2 { this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : any +>this.property : string +> : ^^^^^^ >this : this > : ^^^^ ->property : any -> : ^^^ +>property : string +> : ^^^^^^ >`foo` : "foo" > : ^^^^^ this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : any +>this.property2 : string +> : ^^^^^^ >this : this > : ^^^^ ->property2 : any -> : ^^^ +>property2 : string +> : ^^^^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" diff --git a/tests/baselines/reference/classAttributeInferenceTemplateJS.types b/tests/baselines/reference/classAttributeInferenceTemplateJS.types index f2934c31b6605..1c555c091e866 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplateJS.types +++ b/tests/baselines/reference/classAttributeInferenceTemplateJS.types @@ -23,22 +23,24 @@ class MyClass { this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : any +>this.property : string +> : ^^^^^^ >this : this > : ^^^^ ->property : any -> : ^^^ +>property : string +> : ^^^^^^ >`foo` : "foo" > : ^^^^^ this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : any +>this.property2 : string +> : ^^^^^^ >this : this > : ^^^^ ->property2 : any -> : ^^^ +>property2 : string +> : ^^^^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" @@ -76,22 +78,24 @@ class MyClass2 { this.property = `foo`; >this.property = `foo` : "foo" > : ^^^^^ ->this.property : any +>this.property : string +> : ^^^^^^ >this : this > : ^^^^ ->property : any -> : ^^^ +>property : string +> : ^^^^^^ >`foo` : "foo" > : ^^^^^ this.property2 = `foo-${variable}`; >this.property2 = `foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ ->this.property2 : any +>this.property2 : string +> : ^^^^^^ >this : this > : ^^^^ ->property2 : any -> : ^^^ +>property2 : string +> : ^^^^^^ >`foo-${variable}` : "foo-something" > : ^^^^^^^^^^^^^^^ >variable : "something" diff --git a/tests/baselines/reference/classAttributeInferenceUncheckedJs1.types b/tests/baselines/reference/classAttributeInferenceUncheckedJs1.types index ea81b20d9d6ff..6a86fd07d0fdc 100644 --- a/tests/baselines/reference/classAttributeInferenceUncheckedJs1.types +++ b/tests/baselines/reference/classAttributeInferenceUncheckedJs1.types @@ -17,12 +17,11 @@ class C1 { > : ^^^ this.bar; ->this.bar : undefined -> : ^^^^^^^^^ +>this.bar : any >this : this > : ^^^^ ->bar : undefined -> : ^^^^^^^^^ +>bar : any +> : ^^^ } } @@ -40,8 +39,7 @@ class C2 { > : ^^^^ this.#bar; ->this.#bar : undefined -> : ^^^^^^^^^ +>this.#bar : any >this : this > : ^^^^ } diff --git a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types index 013ed75e2245e..a0a173712e93d 100644 --- a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types +++ b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types @@ -29,7 +29,8 @@ export class Cls { this['x'] = [seed]; >this['x'] = [seed] : number[] > : ^^^^^^^^ ->this['x'] : any +>this['x'] : number[] +> : ^^^^^^^^ >this : this > : ^^^^ >'x' : "x" @@ -42,7 +43,8 @@ export class Cls { this['y'] = { seed }; >this['y'] = { seed } : { seed: number; } > : ^^^^^^^^^^^^^^^^^ ->this['y'] : any +>this['y'] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ >this : this > : ^^^^ >'y' : "y" @@ -55,7 +57,8 @@ export class Cls { this['z'] = `${seed}`; >this['z'] = `${seed}` : string > : ^^^^^^ ->this['z'] : any +>this['z'] : string +> : ^^^^^^ >this : this > : ^^^^ >'z' : "z" @@ -68,7 +71,8 @@ export class Cls { this[0] = [seed]; >this[0] = [seed] : number[] > : ^^^^^^^^ ->this[0] : any +>this[0] : number[] +> : ^^^^^^^^ >this : this > : ^^^^ >0 : 0 diff --git a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js new file mode 100644 index 0000000000000..c13a928f13674 --- /dev/null +++ b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js @@ -0,0 +1,82 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts] //// + +//// [classStaticPropInitializationInferenceWithElementAccess1.ts] +let seed = 0; + +export class Cls1 { + static x; + static y; + static z; + + static 0; + + static { + this["x"] = [32]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + } +} + +export class Cls2 { + static accessor x; + static accessor y; + static accessor z; + + static accessor 0; + + static { + this["x"] = [32]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + } +} + +//// [classStaticPropInitializationInferenceWithElementAccess1.js] +let seed = 0; +export class Cls1 { + static x; + static y; + static z; + static 0; + static { + this["x"] = [32]; + this["y"] = { seed }; + this["z"] = `${seed}`; + this[0] = [seed]; + } +} +export class Cls2 { + static accessor x; + static accessor y; + static accessor z; + static accessor 0; + static { + this["x"] = [32]; + this["y"] = { seed }; + this["z"] = `${seed}`; + this[0] = [seed]; + } +} + + +//// [classStaticPropInitializationInferenceWithElementAccess1.d.ts] +export declare class Cls1 { + static x: number[]; + static y: { + seed: number; + }; + static z: string; + static 0: number[]; +} +export declare class Cls2 { + static accessor x: number[]; + static accessor y: { + seed: number; + }; + static accessor z: string; + static accessor 0: number[]; +} diff --git a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols new file mode 100644 index 0000000000000..5a334fac0a319 --- /dev/null +++ b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols @@ -0,0 +1,79 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts] //// + +=== classStaticPropInitializationInferenceWithElementAccess1.ts === +let seed = 0; +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + +export class Cls1 { +>Cls1 : Symbol(Cls1, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 13)) + + static x; +>x : Symbol(Cls1.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 2, 19)) + + static y; +>y : Symbol(Cls1.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 3, 11)) + + static z; +>z : Symbol(Cls1.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 4, 11)) + + static 0; +>0 : Symbol(Cls1[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 5, 11)) + + static { + this["x"] = [32]; +>this : Symbol(Cls1, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 13)) +>"x" : Symbol(Cls1.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 2, 19)) + + this["y"] = { seed }; +>this : Symbol(Cls1, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 13)) +>"y" : Symbol(Cls1.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 3, 11)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 11, 17)) + + this["z"] = `${seed}`; +>this : Symbol(Cls1, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 13)) +>"z" : Symbol(Cls1.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 4, 11)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + this[0] = [seed]; +>this : Symbol(Cls1, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 13)) +>0 : Symbol(Cls1[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 5, 11)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + } +} + +export class Cls2 { +>Cls2 : Symbol(Cls2, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 16, 1)) + + static accessor x; +>x : Symbol(Cls2.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 18, 19)) + + static accessor y; +>y : Symbol(Cls2.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 19, 20)) + + static accessor z; +>z : Symbol(Cls2.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 20, 20)) + + static accessor 0; +>0 : Symbol(Cls2[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 21, 20)) + + static { + this["x"] = [32]; +>this : Symbol(Cls2, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 16, 1)) +>"x" : Symbol(Cls2.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 18, 19)) + + this["y"] = { seed }; +>this : Symbol(Cls2, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 16, 1)) +>"y" : Symbol(Cls2.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 19, 20)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 27, 17)) + + this["z"] = `${seed}`; +>this : Symbol(Cls2, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 16, 1)) +>"z" : Symbol(Cls2.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 20, 20)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + this[0] = [seed]; +>this : Symbol(Cls2, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 16, 1)) +>0 : Symbol(Cls2[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 21, 20)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + } +} diff --git a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types new file mode 100644 index 0000000000000..c50e5ccb466d0 --- /dev/null +++ b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types @@ -0,0 +1,166 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts] //// + +=== classStaticPropInitializationInferenceWithElementAccess1.ts === +let seed = 0; +>seed : number +> : ^^^^^^ +>0 : 0 +> : ^ + +export class Cls1 { +>Cls1 : Cls1 +> : ^^^^ + + static x; +>x : number[] +> : ^^^^^^^^ + + static y; +>y : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ + + static z; +>z : string +> : ^^^^^^ + + static 0; +>0 : number[] +> : ^^^^^^^^ + + static { + this["x"] = [32]; +>this["x"] = [32] : number[] +> : ^^^^^^^^ +>this["x"] : number[] +> : ^^^^^^^^ +>this : typeof Cls1 +> : ^^^^^^^^^^^ +>"x" : "x" +> : ^^^ +>[32] : number[] +> : ^^^^^^^^ +>32 : 32 +> : ^^ + + this["y"] = { seed }; +>this["y"] = { seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this["y"] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this : typeof Cls1 +> : ^^^^^^^^^^^ +>"y" : "y" +> : ^^^ +>{ seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>seed : number +> : ^^^^^^ + + this["z"] = `${seed}`; +>this["z"] = `${seed}` : string +> : ^^^^^^ +>this["z"] : string +> : ^^^^^^ +>this : typeof Cls1 +> : ^^^^^^^^^^^ +>"z" : "z" +> : ^^^ +>`${seed}` : string +> : ^^^^^^ +>seed : number +> : ^^^^^^ + + this[0] = [seed]; +>this[0] = [seed] : number[] +> : ^^^^^^^^ +>this[0] : number[] +> : ^^^^^^^^ +>this : typeof Cls1 +> : ^^^^^^^^^^^ +>0 : 0 +> : ^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + } +} + +export class Cls2 { +>Cls2 : Cls2 +> : ^^^^ + + static accessor x; +>x : number[] +> : ^^^^^^^^ + + static accessor y; +>y : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ + + static accessor z; +>z : string +> : ^^^^^^ + + static accessor 0; +>0 : number[] +> : ^^^^^^^^ + + static { + this["x"] = [32]; +>this["x"] = [32] : number[] +> : ^^^^^^^^ +>this["x"] : number[] +> : ^^^^^^^^ +>this : typeof Cls2 +> : ^^^^^^^^^^^ +>"x" : "x" +> : ^^^ +>[32] : number[] +> : ^^^^^^^^ +>32 : 32 +> : ^^ + + this["y"] = { seed }; +>this["y"] = { seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this["y"] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this : typeof Cls2 +> : ^^^^^^^^^^^ +>"y" : "y" +> : ^^^ +>{ seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>seed : number +> : ^^^^^^ + + this["z"] = `${seed}`; +>this["z"] = `${seed}` : string +> : ^^^^^^ +>this["z"] : string +> : ^^^^^^ +>this : typeof Cls2 +> : ^^^^^^^^^^^ +>"z" : "z" +> : ^^^ +>`${seed}` : string +> : ^^^^^^ +>seed : number +> : ^^^^^^ + + this[0] = [seed]; +>this[0] = [seed] : number[] +> : ^^^^^^^^ +>this[0] : number[] +> : ^^^^^^^^ +>this : typeof Cls2 +> : ^^^^^^^^^^^ +>0 : 0 +> : ^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + } +} diff --git a/tests/baselines/reference/controlFlowAutoAccessor1.types b/tests/baselines/reference/controlFlowAutoAccessor1.types index 85f456da5d851..c4e8c3865f43f 100644 --- a/tests/baselines/reference/controlFlowAutoAccessor1.types +++ b/tests/baselines/reference/controlFlowAutoAccessor1.types @@ -16,12 +16,12 @@ class Example { this.test = test; >this.test = test : number > : ^^^^^^ ->this.test : any -> : ^^^ +>this.test : number +> : ^^^^^^ >this : this > : ^^^^ ->test : any -> : ^^^ +>test : number +> : ^^^^^^ >test : number > : ^^^^^^ } @@ -55,12 +55,12 @@ class Example2 { this.test = test; >this.test = test : number | undefined > : ^^^^^^^^^^^^^^^^^^ ->this.test : any -> : ^^^ +>this.test : number | undefined +> : ^^^^^^^^^^^^^^^^^^ >this : this > : ^^^^ ->test : any -> : ^^^ +>test : number | undefined +> : ^^^^^^^^^^^^^^^^^^ >test : number | undefined > : ^^^^^^^^^^^^^^^^^^ } @@ -108,12 +108,12 @@ class Example3 { this.value = n; >this.value = n : number > : ^^^^^^ ->this.value : any -> : ^^^ +>this.value : number | null +> : ^^^^^^^^^^^^^ >this : this > : ^^^^ ->value : any -> : ^^^ +>value : number | null +> : ^^^^^^^^^^^^^ >n : number > : ^^^^^^ @@ -128,12 +128,12 @@ class Example3 { this.value = null; >this.value = null : null > : ^^^^ ->this.value : any -> : ^^^ +>this.value : number | null +> : ^^^^^^^^^^^^^ >this : this > : ^^^^ ->value : any -> : ^^^ +>value : number | null +> : ^^^^^^^^^^^^^ } } } diff --git a/tests/baselines/reference/controlFlowPrivateClassField.types b/tests/baselines/reference/controlFlowPrivateClassField.types index 6ab1a52d31a53..fd2ddbd1e4292 100644 --- a/tests/baselines/reference/controlFlowPrivateClassField.types +++ b/tests/baselines/reference/controlFlowPrivateClassField.types @@ -16,7 +16,8 @@ class Example { this.#test = test; >this.#test = test : number > : ^^^^^^ ->this.#test : any +>this.#test : number +> : ^^^^^^ >this : this > : ^^^^ >test : number @@ -50,7 +51,8 @@ class Example2 { this.#test = test; >this.#test = test : number | undefined > : ^^^^^^^^^^^^^^^^^^ ->this.#test : any +>this.#test : number | undefined +> : ^^^^^^^^^^^^^^^^^^ >this : this > : ^^^^ >test : number | undefined diff --git a/tests/baselines/reference/genericSetterInClassTypeJsDoc.types b/tests/baselines/reference/genericSetterInClassTypeJsDoc.types index cea5b12645b85..e128037dd9c02 100644 --- a/tests/baselines/reference/genericSetterInClassTypeJsDoc.types +++ b/tests/baselines/reference/genericSetterInClassTypeJsDoc.types @@ -20,7 +20,8 @@ this.#value = initialValue; >this.#value = initialValue : T > : ^ ->this.#value : any +>this.#value : T +> : ^ >this : this > : ^^^^ >initialValue : T diff --git a/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types b/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types index efe6863aa0166..cea9ea7054bd5 100644 --- a/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types +++ b/tests/baselines/reference/privateNameUncheckedJsOptionalChain.types @@ -17,8 +17,8 @@ class C { > : ^^^^ this?.#bar; ->this?.#bar : undefined -> : ^^^^^^^^^ +>this?.#bar : any +> : ^^^ >this : this > : ^^^^ } diff --git a/tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts b/tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts new file mode 100644 index 0000000000000..49407289767e5 --- /dev/null +++ b/tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts @@ -0,0 +1,37 @@ +// @strict: true +// @target: esnext +// @declaration: true + +let seed = 0; + +export class Cls1 { + static x; + static y; + static z; + + static 0; + + static { + this["x"] = [32]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + } +} + +export class Cls2 { + static accessor x; + static accessor y; + static accessor z; + + static accessor 0; + + static { + this["x"] = [32]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + } +} \ No newline at end of file From 96fe0a7085d6624918072b03789816886f4a1bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 4 Nov 2024 12:13:41 +0100 Subject: [PATCH 3/8] fix comment --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8248a4208d84c..dffb14bce6e0d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31473,8 +31473,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case AssignmentDeclarationKind.ThisProperty: const lhsSymbol = getSymbolForExpression(binaryExpression.left); const decl = lhsSymbol && lhsSymbol.valueDeclaration; - // Unannotated, uninitialized property declarations have a type implied by their usage in the constructor. - // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case when the assignment declaration is in the constructor + // Unannotated, uninitialized property declarations have a type implied by their usage in the constructor or static blocks. + // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case when the assignment declaration is in the respective auto container if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl)) && (!isAccessExpression(binaryExpression.left) || isThisPropertyAccessInAutoContainer(binaryExpression.left, lhsSymbol))) { const overallAnnotation = getEffectiveTypeAnnotationNode(decl); return (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) || From 7e5bf5f6075bcd09ba6ff96e7786fbb57814f659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 4 Nov 2024 12:27:51 +0100 Subject: [PATCH 4/8] tweak code --- src/compiler/checker.ts | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dffb14bce6e0d..f5700d942626c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11298,23 +11298,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); - if (!isClassStaticBlockDeclaration(thisContainer)) { - return false; - } - return (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent; + return isClassStaticBlockDeclaration(thisContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent; } if (!isConstructorDeclaredProperty(prop) && (!isThisProperty(node) || !isAutoTypedProperty(prop))) { return false; } const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); - if (thisContainer === getDeclaringConstructor(prop)) { - return true; - } - const classLikeDeclaration = prop.parent && getClassLikeDeclarationOfSymbol(prop.parent); - if (!classLikeDeclaration) { - return false; - } - return thisContainer === findConstructorDeclaration(classLikeDeclaration); + return isConstructorDeclaration(thisContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent || thisContainer === getDeclaringConstructor(prop); } function getDeclaringConstructor(symbol: Symbol) { From 19d3e635700c7b3c4dcf2dad3c16df0ef57cd2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 4 Nov 2024 12:54:31 +0100 Subject: [PATCH 5/8] fixed IIFEs --- src/compiler/checker.ts | 4 +- ...itializationInferenceWithElementAccess1.js | 41 +++ ...izationInferenceWithElementAccess1.symbols | 43 ++++ ...alizationInferenceWithElementAccess1.types | 92 +++++++ .../classAttributeInferenceTemplate.js | 56 ++++ .../classAttributeInferenceTemplate.symbols | 66 +++++ .../classAttributeInferenceTemplate.types | 130 ++++++++++ .../classAttributeInferenceTemplateJS.symbols | 66 +++++ .../classAttributeInferenceTemplateJS.types | 130 ++++++++++ ...lizationInferenceWithElementAccess.symbols | 43 ++++ ...ializationInferenceWithElementAccess.types | 92 +++++++ .../classStaticPropInferenceTemplate1.js | 110 ++++++++ .../classStaticPropInferenceTemplate1.symbols | 129 ++++++++++ .../classStaticPropInferenceTemplate1.types | 243 ++++++++++++++++++ ...itializationInferenceWithElementAccess1.js | 91 ++++++- ...izationInferenceWithElementAccess1.symbols | 89 ++++++- ...alizationInferenceWithElementAccess1.types | 207 ++++++++++++++- ...itializationInferenceWithElementAccess1.ts | 18 ++ .../classAttributeInferenceTemplate.ts | 32 +++ .../classAttributeInferenceTemplateJS.ts | 32 +++ ...nitializationInferenceWithElementAccess.ts | 18 ++ .../classStaticPropInferenceTemplate1.ts | 62 +++++ ...itializationInferenceWithElementAccess1.ts | 42 ++- 23 files changed, 1810 insertions(+), 26 deletions(-) create mode 100644 tests/baselines/reference/classStaticPropInferenceTemplate1.js create mode 100644 tests/baselines/reference/classStaticPropInferenceTemplate1.symbols create mode 100644 tests/baselines/reference/classStaticPropInferenceTemplate1.types create mode 100644 tests/cases/conformance/classes/classStaticBlock/classStaticPropInferenceTemplate1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f5700d942626c..311f9f540c1e3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11297,13 +11297,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isThisProperty(node) || !isAutoTypedProperty(prop)) { return false; } - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); + const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); return isClassStaticBlockDeclaration(thisContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent; } if (!isConstructorDeclaredProperty(prop) && (!isThisProperty(node) || !isAutoTypedProperty(prop))) { return false; } - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); + const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); return isConstructorDeclaration(thisContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent || thisContainer === getDeclaringConstructor(prop); } diff --git a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.js b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.js index 1f0d50879c723..f05d81f3e69fa 100644 --- a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.js +++ b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.js @@ -16,6 +16,24 @@ export class Cls { this[0] = [seed]; } } + +export class Cls2 { + accessor x; + accessor y; + accessor z; + + accessor 0; + + constructor(seed: number) { + (() => { + this['x'] = [seed]; + this['y'] = { seed }; + this['z'] = `${seed}`; + + this[0] = [seed]; + })(); + } +} //// [classAccessorInitializationInferenceWithElementAccess1.js] @@ -31,6 +49,20 @@ export class Cls { this[0] = [seed]; } } +export class Cls2 { + accessor x; + accessor y; + accessor z; + accessor 0; + constructor(seed) { + (() => { + this['x'] = [seed]; + this['y'] = { seed }; + this['z'] = `${seed}`; + this[0] = [seed]; + })(); + } +} //// [classAccessorInitializationInferenceWithElementAccess1.d.ts] @@ -43,3 +75,12 @@ export declare class Cls { accessor 0: number[]; constructor(seed: number); } +export declare class Cls2 { + accessor x: number[]; + accessor y: { + seed: number; + }; + accessor z: string; + accessor 0: number[]; + constructor(seed: number); +} diff --git a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.symbols b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.symbols index 4f328fa9da5b3..7868d54e7f655 100644 --- a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.symbols +++ b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.symbols @@ -41,3 +41,46 @@ export class Cls { } } +export class Cls2 { +>Cls2 : Symbol(Cls2, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 14, 1)) + + accessor x; +>x : Symbol(Cls2.x, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 16, 19)) + + accessor y; +>y : Symbol(Cls2.y, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 17, 15)) + + accessor z; +>z : Symbol(Cls2.z, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 18, 15)) + + accessor 0; +>0 : Symbol(Cls2[0], Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 19, 15)) + + constructor(seed: number) { +>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 23, 16)) + + (() => { + this['x'] = [seed]; +>this : Symbol(Cls2, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 14, 1)) +>'x' : Symbol(Cls2.x, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 16, 19)) +>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 23, 16)) + + this['y'] = { seed }; +>this : Symbol(Cls2, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 14, 1)) +>'y' : Symbol(Cls2.y, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 17, 15)) +>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 26, 25)) + + this['z'] = `${seed}`; +>this : Symbol(Cls2, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 14, 1)) +>'z' : Symbol(Cls2.z, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 18, 15)) +>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 23, 16)) + + this[0] = [seed]; +>this : Symbol(Cls2, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 14, 1)) +>0 : Symbol(Cls2[0], Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 19, 15)) +>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 23, 16)) + + })(); + } +} + diff --git a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types index 63ed461d086ca..ac73cecc6b101 100644 --- a/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types +++ b/tests/baselines/reference/classAccessorInitializationInferenceWithElementAccess1.types @@ -83,3 +83,95 @@ export class Cls { } } +export class Cls2 { +>Cls2 : Cls2 +> : ^^^^ + + accessor x; +>x : number[] +> : ^^^^^^^^ + + accessor y; +>y : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ + + accessor z; +>z : string +> : ^^^^^^ + + accessor 0; +>0 : number[] +> : ^^^^^^^^ + + constructor(seed: number) { +>seed : number +> : ^^^^^^ + + (() => { +>(() => { this['x'] = [seed]; this['y'] = { seed }; this['z'] = `${seed}`; this[0] = [seed]; })() : void +> : ^^^^ +>(() => { this['x'] = [seed]; this['y'] = { seed }; this['z'] = `${seed}`; this[0] = [seed]; }) : () => void +> : ^^^^^^^^^^ +>() => { this['x'] = [seed]; this['y'] = { seed }; this['z'] = `${seed}`; this[0] = [seed]; } : () => void +> : ^^^^^^^^^^ + + this['x'] = [seed]; +>this['x'] = [seed] : number[] +> : ^^^^^^^^ +>this['x'] : number[] +> : ^^^^^^^^ +>this : this +> : ^^^^ +>'x' : "x" +> : ^^^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + this['y'] = { seed }; +>this['y'] = { seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this['y'] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this : this +> : ^^^^ +>'y' : "y" +> : ^^^ +>{ seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>seed : number +> : ^^^^^^ + + this['z'] = `${seed}`; +>this['z'] = `${seed}` : string +> : ^^^^^^ +>this['z'] : string +> : ^^^^^^ +>this : this +> : ^^^^ +>'z' : "z" +> : ^^^ +>`${seed}` : string +> : ^^^^^^ +>seed : number +> : ^^^^^^ + + this[0] = [seed]; +>this[0] = [seed] : number[] +> : ^^^^^^^^ +>this[0] : number[] +> : ^^^^^^^^ +>this : this +> : ^^^^ +>0 : 0 +> : ^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + })(); + } +} + diff --git a/tests/baselines/reference/classAttributeInferenceTemplate.js b/tests/baselines/reference/classAttributeInferenceTemplate.js index 92ecb3ba27560..4bb3b504f4dd0 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplate.js +++ b/tests/baselines/reference/classAttributeInferenceTemplate.js @@ -28,6 +28,38 @@ class MyClass2 { const localProperty = `foo-${variable}`; } } + +class MyClass3 { + property; + property2; + + constructor() { + (() => { + const variable = 'something' + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} + +class MyClass4 { + accessor property; + accessor property2; + + constructor() { + (() => { + const variable = 'something' + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} //// [classAttributeInferenceTemplate.js] @@ -52,3 +84,27 @@ class MyClass2 { const localProperty = `foo-${variable}`; } } +class MyClass3 { + property; + property2; + constructor() { + (() => { + const variable = 'something'; + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; + })(); + } +} +class MyClass4 { + accessor property; + accessor property2; + constructor() { + (() => { + const variable = 'something'; + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; + })(); + } +} diff --git a/tests/baselines/reference/classAttributeInferenceTemplate.symbols b/tests/baselines/reference/classAttributeInferenceTemplate.symbols index 5dd5d39fbcd14..ed05b243c7e74 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplate.symbols +++ b/tests/baselines/reference/classAttributeInferenceTemplate.symbols @@ -61,3 +61,69 @@ class MyClass2 { } } +class MyClass3 { +>MyClass3 : Symbol(MyClass3, Decl(classAttributeInferenceTemplate.ts, 26, 1)) + + property; +>property : Symbol(MyClass3.property, Decl(classAttributeInferenceTemplate.ts, 28, 16)) + + property2; +>property2 : Symbol(MyClass3.property2, Decl(classAttributeInferenceTemplate.ts, 29, 13)) + + constructor() { + (() => { + const variable = 'something' +>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 34, 17)) + + this.property = `foo`; +>this.property : Symbol(MyClass3.property, Decl(classAttributeInferenceTemplate.ts, 28, 16)) +>this : Symbol(MyClass3, Decl(classAttributeInferenceTemplate.ts, 26, 1)) +>property : Symbol(MyClass3.property, Decl(classAttributeInferenceTemplate.ts, 28, 16)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass3.property2, Decl(classAttributeInferenceTemplate.ts, 29, 13)) +>this : Symbol(MyClass3, Decl(classAttributeInferenceTemplate.ts, 26, 1)) +>property2 : Symbol(MyClass3.property2, Decl(classAttributeInferenceTemplate.ts, 29, 13)) +>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 34, 17)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(classAttributeInferenceTemplate.ts, 39, 17)) +>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 34, 17)) + + })(); + } +} + +class MyClass4 { +>MyClass4 : Symbol(MyClass4, Decl(classAttributeInferenceTemplate.ts, 42, 1)) + + accessor property; +>property : Symbol(MyClass4.property, Decl(classAttributeInferenceTemplate.ts, 44, 16)) + + accessor property2; +>property2 : Symbol(MyClass4.property2, Decl(classAttributeInferenceTemplate.ts, 45, 22)) + + constructor() { + (() => { + const variable = 'something' +>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 50, 17)) + + this.property = `foo`; +>this.property : Symbol(MyClass4.property, Decl(classAttributeInferenceTemplate.ts, 44, 16)) +>this : Symbol(MyClass4, Decl(classAttributeInferenceTemplate.ts, 42, 1)) +>property : Symbol(MyClass4.property, Decl(classAttributeInferenceTemplate.ts, 44, 16)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass4.property2, Decl(classAttributeInferenceTemplate.ts, 45, 22)) +>this : Symbol(MyClass4, Decl(classAttributeInferenceTemplate.ts, 42, 1)) +>property2 : Symbol(MyClass4.property2, Decl(classAttributeInferenceTemplate.ts, 45, 22)) +>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 50, 17)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(classAttributeInferenceTemplate.ts, 55, 17)) +>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 50, 17)) + + })(); + } +} + diff --git a/tests/baselines/reference/classAttributeInferenceTemplate.types b/tests/baselines/reference/classAttributeInferenceTemplate.types index 849205039f91a..1c669f8f23eff 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplate.types +++ b/tests/baselines/reference/classAttributeInferenceTemplate.types @@ -111,3 +111,133 @@ class MyClass2 { } } +class MyClass3 { +>MyClass3 : MyClass3 +> : ^^^^^^^^ + + property; +>property : string +> : ^^^^^^ + + property2; +>property2 : string +> : ^^^^^^ + + constructor() { + (() => { +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; })() : void +> : ^^^^ +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; }) : () => void +> : ^^^^^^^^^^ +>() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; } : () => void +> : ^^^^^^^^^^ + + const variable = 'something' +>variable : "something" +> : ^^^^^^^^^^^ +>'something' : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + })(); + } +} + +class MyClass4 { +>MyClass4 : MyClass4 +> : ^^^^^^^^ + + accessor property; +>property : string +> : ^^^^^^ + + accessor property2; +>property2 : string +> : ^^^^^^ + + constructor() { + (() => { +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; })() : void +> : ^^^^ +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; }) : () => void +> : ^^^^^^^^^^ +>() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; } : () => void +> : ^^^^^^^^^^ + + const variable = 'something' +>variable : "something" +> : ^^^^^^^^^^^ +>'something' : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + })(); + } +} + diff --git a/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols b/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols index c7b17f892a942..39e68b9393207 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols +++ b/tests/baselines/reference/classAttributeInferenceTemplateJS.symbols @@ -61,3 +61,69 @@ class MyClass2 { } } +class MyClass3 { +>MyClass3 : Symbol(MyClass3, Decl(index.js, 26, 1)) + + property; +>property : Symbol(MyClass3.property, Decl(index.js, 28, 16)) + + property2; +>property2 : Symbol(MyClass3.property2, Decl(index.js, 29, 13)) + + constructor() { + (() => { + const variable = 'something' +>variable : Symbol(variable, Decl(index.js, 34, 17)) + + this.property = `foo`; +>this.property : Symbol(MyClass3.property, Decl(index.js, 28, 16)) +>this : Symbol(MyClass3, Decl(index.js, 26, 1)) +>property : Symbol(MyClass3.property, Decl(index.js, 28, 16)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass3.property2, Decl(index.js, 29, 13)) +>this : Symbol(MyClass3, Decl(index.js, 26, 1)) +>property2 : Symbol(MyClass3.property2, Decl(index.js, 29, 13)) +>variable : Symbol(variable, Decl(index.js, 34, 17)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(index.js, 39, 17)) +>variable : Symbol(variable, Decl(index.js, 34, 17)) + + })(); + } +} + +class MyClass4 { +>MyClass4 : Symbol(MyClass4, Decl(index.js, 42, 1)) + + accessor property; +>property : Symbol(MyClass4.property, Decl(index.js, 44, 16)) + + accessor property2; +>property2 : Symbol(MyClass4.property2, Decl(index.js, 45, 22)) + + constructor() { + (() => { + const variable = 'something' +>variable : Symbol(variable, Decl(index.js, 50, 17)) + + this.property = `foo`; +>this.property : Symbol(MyClass4.property, Decl(index.js, 44, 16)) +>this : Symbol(MyClass4, Decl(index.js, 42, 1)) +>property : Symbol(MyClass4.property, Decl(index.js, 44, 16)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass4.property2, Decl(index.js, 45, 22)) +>this : Symbol(MyClass4, Decl(index.js, 42, 1)) +>property2 : Symbol(MyClass4.property2, Decl(index.js, 45, 22)) +>variable : Symbol(variable, Decl(index.js, 50, 17)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(index.js, 55, 17)) +>variable : Symbol(variable, Decl(index.js, 50, 17)) + + })(); + } +} + diff --git a/tests/baselines/reference/classAttributeInferenceTemplateJS.types b/tests/baselines/reference/classAttributeInferenceTemplateJS.types index 1c555c091e866..87669c92ec5a8 100644 --- a/tests/baselines/reference/classAttributeInferenceTemplateJS.types +++ b/tests/baselines/reference/classAttributeInferenceTemplateJS.types @@ -111,3 +111,133 @@ class MyClass2 { } } +class MyClass3 { +>MyClass3 : MyClass3 +> : ^^^^^^^^ + + property; +>property : string +> : ^^^^^^ + + property2; +>property2 : string +> : ^^^^^^ + + constructor() { + (() => { +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; })() : void +> : ^^^^ +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; }) : () => void +> : ^^^^^^^^^^ +>() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; } : () => void +> : ^^^^^^^^^^ + + const variable = 'something' +>variable : "something" +> : ^^^^^^^^^^^ +>'something' : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + })(); + } +} + +class MyClass4 { +>MyClass4 : MyClass4 +> : ^^^^^^^^ + + accessor property; +>property : string +> : ^^^^^^ + + accessor property2; +>property2 : string +> : ^^^^^^ + + constructor() { + (() => { +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; })() : void +> : ^^^^ +>(() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; }) : () => void +> : ^^^^^^^^^^ +>() => { const variable = 'something' this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; } : () => void +> : ^^^^^^^^^^ + + const variable = 'something' +>variable : "something" +> : ^^^^^^^^^^^ +>'something' : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : this +> : ^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + })(); + } +} + diff --git a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.symbols b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.symbols index 04da38aefbd25..4cdde30e60f16 100644 --- a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.symbols +++ b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.symbols @@ -41,3 +41,46 @@ export class Cls { >seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 8, 16)) } } + +export class Cls2 { +>Cls2 : Symbol(Cls2, Decl(classPropInitializationInferenceWithElementAccess.ts, 15, 1)) + + x; +>x : Symbol(Cls2.x, Decl(classPropInitializationInferenceWithElementAccess.ts, 17, 19)) + + y; +>y : Symbol(Cls2.y, Decl(classPropInitializationInferenceWithElementAccess.ts, 18, 6)) + + z; +>z : Symbol(Cls2.z, Decl(classPropInitializationInferenceWithElementAccess.ts, 19, 6)) + + 0; +>0 : Symbol(Cls2[0], Decl(classPropInitializationInferenceWithElementAccess.ts, 20, 6)) + + constructor(seed: number) { +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 24, 16)) + + (() => { + this['x'] = [seed]; +>this : Symbol(Cls2, Decl(classPropInitializationInferenceWithElementAccess.ts, 15, 1)) +>'x' : Symbol(Cls2.x, Decl(classPropInitializationInferenceWithElementAccess.ts, 17, 19)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 24, 16)) + + this['y'] = { seed }; +>this : Symbol(Cls2, Decl(classPropInitializationInferenceWithElementAccess.ts, 15, 1)) +>'y' : Symbol(Cls2.y, Decl(classPropInitializationInferenceWithElementAccess.ts, 18, 6)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 27, 25)) + + this['z'] = `${seed}`; +>this : Symbol(Cls2, Decl(classPropInitializationInferenceWithElementAccess.ts, 15, 1)) +>'z' : Symbol(Cls2.z, Decl(classPropInitializationInferenceWithElementAccess.ts, 19, 6)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 24, 16)) + + this[0] = [seed]; +>this : Symbol(Cls2, Decl(classPropInitializationInferenceWithElementAccess.ts, 15, 1)) +>0 : Symbol(Cls2[0], Decl(classPropInitializationInferenceWithElementAccess.ts, 20, 6)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 24, 16)) + + })(); + } +} diff --git a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types index a0a173712e93d..f5e276130a7f7 100644 --- a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types +++ b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types @@ -83,3 +83,95 @@ export class Cls { > : ^^^^^^ } } + +export class Cls2 { +>Cls2 : Cls2 +> : ^^^^ + + x; +>x : number[] +> : ^^^^^^^^ + + y; +>y : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ + + z; +>z : string +> : ^^^^^^ + + 0; +>0 : number[] +> : ^^^^^^^^ + + constructor(seed: number) { +>seed : number +> : ^^^^^^ + + (() => { +>(() => { this['x'] = [seed]; this['y'] = { seed }; this['z'] = `${seed}`; this[0] = [seed]; })() : void +> : ^^^^ +>(() => { this['x'] = [seed]; this['y'] = { seed }; this['z'] = `${seed}`; this[0] = [seed]; }) : () => void +> : ^^^^^^^^^^ +>() => { this['x'] = [seed]; this['y'] = { seed }; this['z'] = `${seed}`; this[0] = [seed]; } : () => void +> : ^^^^^^^^^^ + + this['x'] = [seed]; +>this['x'] = [seed] : number[] +> : ^^^^^^^^ +>this['x'] : number[] +> : ^^^^^^^^ +>this : this +> : ^^^^ +>'x' : "x" +> : ^^^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + this['y'] = { seed }; +>this['y'] = { seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this['y'] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this : this +> : ^^^^ +>'y' : "y" +> : ^^^ +>{ seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>seed : number +> : ^^^^^^ + + this['z'] = `${seed}`; +>this['z'] = `${seed}` : string +> : ^^^^^^ +>this['z'] : string +> : ^^^^^^ +>this : this +> : ^^^^ +>'z' : "z" +> : ^^^ +>`${seed}` : string +> : ^^^^^^ +>seed : number +> : ^^^^^^ + + this[0] = [seed]; +>this[0] = [seed] : number[] +> : ^^^^^^^^ +>this[0] : number[] +> : ^^^^^^^^ +>this : this +> : ^^^^ +>0 : 0 +> : ^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + })(); + } +} diff --git a/tests/baselines/reference/classStaticPropInferenceTemplate1.js b/tests/baselines/reference/classStaticPropInferenceTemplate1.js new file mode 100644 index 0000000000000..9de655cde9dcd --- /dev/null +++ b/tests/baselines/reference/classStaticPropInferenceTemplate1.js @@ -0,0 +1,110 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticPropInferenceTemplate1.ts] //// + +//// [classStaticPropInferenceTemplate1.ts] +class MyClass { + static property; + static property2; + + static { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + } +} + +class MyClass2 { + static accessor property; + static accessor property2; + + static { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + } +} + +class MyClass3 { + static property; + static property2; + + static { + (() => { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} + +class MyClass4 { + static accessor property; + static accessor property2; + + static { + (() => { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} + + +//// [classStaticPropInferenceTemplate1.js] +"use strict"; +class MyClass { + static property; + static property2; + static { + const variable = "something"; + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; + } +} +class MyClass2 { + static accessor property; + static accessor property2; + static { + const variable = "something"; + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; + } +} +class MyClass3 { + static property; + static property2; + static { + (() => { + const variable = "something"; + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; + })(); + } +} +class MyClass4 { + static accessor property; + static accessor property2; + static { + (() => { + const variable = "something"; + this.property = `foo`; + this.property2 = `foo-${variable}`; + const localProperty = `foo-${variable}`; + })(); + } +} diff --git a/tests/baselines/reference/classStaticPropInferenceTemplate1.symbols b/tests/baselines/reference/classStaticPropInferenceTemplate1.symbols new file mode 100644 index 0000000000000..500a5840b2730 --- /dev/null +++ b/tests/baselines/reference/classStaticPropInferenceTemplate1.symbols @@ -0,0 +1,129 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticPropInferenceTemplate1.ts] //// + +=== classStaticPropInferenceTemplate1.ts === +class MyClass { +>MyClass : Symbol(MyClass, Decl(classStaticPropInferenceTemplate1.ts, 0, 0)) + + static property; +>property : Symbol(MyClass.property, Decl(classStaticPropInferenceTemplate1.ts, 0, 15)) + + static property2; +>property2 : Symbol(MyClass.property2, Decl(classStaticPropInferenceTemplate1.ts, 1, 18)) + + static { + const variable = "something"; +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 5, 9)) + + this.property = `foo`; +>this.property : Symbol(MyClass.property, Decl(classStaticPropInferenceTemplate1.ts, 0, 15)) +>this : Symbol(MyClass, Decl(classStaticPropInferenceTemplate1.ts, 0, 0)) +>property : Symbol(MyClass.property, Decl(classStaticPropInferenceTemplate1.ts, 0, 15)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass.property2, Decl(classStaticPropInferenceTemplate1.ts, 1, 18)) +>this : Symbol(MyClass, Decl(classStaticPropInferenceTemplate1.ts, 0, 0)) +>property2 : Symbol(MyClass.property2, Decl(classStaticPropInferenceTemplate1.ts, 1, 18)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 5, 9)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(classStaticPropInferenceTemplate1.ts, 10, 9)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 5, 9)) + } +} + +class MyClass2 { +>MyClass2 : Symbol(MyClass2, Decl(classStaticPropInferenceTemplate1.ts, 12, 1)) + + static accessor property; +>property : Symbol(MyClass2.property, Decl(classStaticPropInferenceTemplate1.ts, 14, 16)) + + static accessor property2; +>property2 : Symbol(MyClass2.property2, Decl(classStaticPropInferenceTemplate1.ts, 15, 27)) + + static { + const variable = "something"; +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 19, 9)) + + this.property = `foo`; +>this.property : Symbol(MyClass2.property, Decl(classStaticPropInferenceTemplate1.ts, 14, 16)) +>this : Symbol(MyClass2, Decl(classStaticPropInferenceTemplate1.ts, 12, 1)) +>property : Symbol(MyClass2.property, Decl(classStaticPropInferenceTemplate1.ts, 14, 16)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass2.property2, Decl(classStaticPropInferenceTemplate1.ts, 15, 27)) +>this : Symbol(MyClass2, Decl(classStaticPropInferenceTemplate1.ts, 12, 1)) +>property2 : Symbol(MyClass2.property2, Decl(classStaticPropInferenceTemplate1.ts, 15, 27)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 19, 9)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(classStaticPropInferenceTemplate1.ts, 24, 9)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 19, 9)) + } +} + +class MyClass3 { +>MyClass3 : Symbol(MyClass3, Decl(classStaticPropInferenceTemplate1.ts, 26, 1)) + + static property; +>property : Symbol(MyClass3.property, Decl(classStaticPropInferenceTemplate1.ts, 28, 16)) + + static property2; +>property2 : Symbol(MyClass3.property2, Decl(classStaticPropInferenceTemplate1.ts, 29, 18)) + + static { + (() => { + const variable = "something"; +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 34, 11)) + + this.property = `foo`; +>this.property : Symbol(MyClass3.property, Decl(classStaticPropInferenceTemplate1.ts, 28, 16)) +>this : Symbol(MyClass3, Decl(classStaticPropInferenceTemplate1.ts, 26, 1)) +>property : Symbol(MyClass3.property, Decl(classStaticPropInferenceTemplate1.ts, 28, 16)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass3.property2, Decl(classStaticPropInferenceTemplate1.ts, 29, 18)) +>this : Symbol(MyClass3, Decl(classStaticPropInferenceTemplate1.ts, 26, 1)) +>property2 : Symbol(MyClass3.property2, Decl(classStaticPropInferenceTemplate1.ts, 29, 18)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 34, 11)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(classStaticPropInferenceTemplate1.ts, 39, 11)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 34, 11)) + + })(); + } +} + +class MyClass4 { +>MyClass4 : Symbol(MyClass4, Decl(classStaticPropInferenceTemplate1.ts, 42, 1)) + + static accessor property; +>property : Symbol(MyClass4.property, Decl(classStaticPropInferenceTemplate1.ts, 44, 16)) + + static accessor property2; +>property2 : Symbol(MyClass4.property2, Decl(classStaticPropInferenceTemplate1.ts, 45, 27)) + + static { + (() => { + const variable = "something"; +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 50, 11)) + + this.property = `foo`; +>this.property : Symbol(MyClass4.property, Decl(classStaticPropInferenceTemplate1.ts, 44, 16)) +>this : Symbol(MyClass4, Decl(classStaticPropInferenceTemplate1.ts, 42, 1)) +>property : Symbol(MyClass4.property, Decl(classStaticPropInferenceTemplate1.ts, 44, 16)) + + this.property2 = `foo-${variable}`; +>this.property2 : Symbol(MyClass4.property2, Decl(classStaticPropInferenceTemplate1.ts, 45, 27)) +>this : Symbol(MyClass4, Decl(classStaticPropInferenceTemplate1.ts, 42, 1)) +>property2 : Symbol(MyClass4.property2, Decl(classStaticPropInferenceTemplate1.ts, 45, 27)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 50, 11)) + + const localProperty = `foo-${variable}`; +>localProperty : Symbol(localProperty, Decl(classStaticPropInferenceTemplate1.ts, 55, 11)) +>variable : Symbol(variable, Decl(classStaticPropInferenceTemplate1.ts, 50, 11)) + + })(); + } +} + diff --git a/tests/baselines/reference/classStaticPropInferenceTemplate1.types b/tests/baselines/reference/classStaticPropInferenceTemplate1.types new file mode 100644 index 0000000000000..ea5769c1f8186 --- /dev/null +++ b/tests/baselines/reference/classStaticPropInferenceTemplate1.types @@ -0,0 +1,243 @@ +//// [tests/cases/conformance/classes/classStaticBlock/classStaticPropInferenceTemplate1.ts] //// + +=== classStaticPropInferenceTemplate1.ts === +class MyClass { +>MyClass : MyClass +> : ^^^^^^^ + + static property; +>property : string +> : ^^^^^^ + + static property2; +>property2 : string +> : ^^^^^^ + + static { + const variable = "something"; +>variable : "something" +> : ^^^^^^^^^^^ +>"something" : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : typeof MyClass +> : ^^^^^^^^^^^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : typeof MyClass +> : ^^^^^^^^^^^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + } +} + +class MyClass2 { +>MyClass2 : MyClass2 +> : ^^^^^^^^ + + static accessor property; +>property : string +> : ^^^^^^ + + static accessor property2; +>property2 : string +> : ^^^^^^ + + static { + const variable = "something"; +>variable : "something" +> : ^^^^^^^^^^^ +>"something" : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : typeof MyClass2 +> : ^^^^^^^^^^^^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : typeof MyClass2 +> : ^^^^^^^^^^^^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + } +} + +class MyClass3 { +>MyClass3 : MyClass3 +> : ^^^^^^^^ + + static property; +>property : string +> : ^^^^^^ + + static property2; +>property2 : string +> : ^^^^^^ + + static { + (() => { +>(() => { const variable = "something"; this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; })() : void +> : ^^^^ +>(() => { const variable = "something"; this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; }) : () => void +> : ^^^^^^^^^^ +>() => { const variable = "something"; this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; } : () => void +> : ^^^^^^^^^^ + + const variable = "something"; +>variable : "something" +> : ^^^^^^^^^^^ +>"something" : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : typeof MyClass3 +> : ^^^^^^^^^^^^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : typeof MyClass3 +> : ^^^^^^^^^^^^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + })(); + } +} + +class MyClass4 { +>MyClass4 : MyClass4 +> : ^^^^^^^^ + + static accessor property; +>property : string +> : ^^^^^^ + + static accessor property2; +>property2 : string +> : ^^^^^^ + + static { + (() => { +>(() => { const variable = "something"; this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; })() : void +> : ^^^^ +>(() => { const variable = "something"; this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; }) : () => void +> : ^^^^^^^^^^ +>() => { const variable = "something"; this.property = `foo`; this.property2 = `foo-${variable}`; const localProperty = `foo-${variable}`; } : () => void +> : ^^^^^^^^^^ + + const variable = "something"; +>variable : "something" +> : ^^^^^^^^^^^ +>"something" : "something" +> : ^^^^^^^^^^^ + + this.property = `foo`; +>this.property = `foo` : "foo" +> : ^^^^^ +>this.property : string +> : ^^^^^^ +>this : typeof MyClass4 +> : ^^^^^^^^^^^^^^^ +>property : string +> : ^^^^^^ +>`foo` : "foo" +> : ^^^^^ + + this.property2 = `foo-${variable}`; +>this.property2 = `foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>this.property2 : string +> : ^^^^^^ +>this : typeof MyClass4 +> : ^^^^^^^^^^^^^^^ +>property2 : string +> : ^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + const localProperty = `foo-${variable}`; +>localProperty : "foo-something" +> : ^^^^^^^^^^^^^^^ +>`foo-${variable}` : "foo-something" +> : ^^^^^^^^^^^^^^^ +>variable : "something" +> : ^^^^^^^^^^^ + + })(); + } +} + diff --git a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js index c13a928f13674..a16e3c967b570 100644 --- a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js +++ b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.js @@ -11,7 +11,7 @@ export class Cls1 { static 0; static { - this["x"] = [32]; + this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; @@ -27,13 +27,50 @@ export class Cls2 { static accessor 0; static { - this["x"] = [32]; + this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; } -} +} + +export class Cls3 { + static x; + static y; + static z; + + static 0; + + static { + (() => { + this["x"] = [seed]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + })(); + } +} + +export class Cls4 { + static accessor x; + static accessor y; + static accessor z; + + static accessor 0; + + static { + (() => { + this["x"] = [seed]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + })(); + } +} + //// [classStaticPropInitializationInferenceWithElementAccess1.js] let seed = 0; @@ -43,7 +80,7 @@ export class Cls1 { static z; static 0; static { - this["x"] = [32]; + this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; @@ -55,12 +92,40 @@ export class Cls2 { static accessor z; static accessor 0; static { - this["x"] = [32]; + this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; } } +export class Cls3 { + static x; + static y; + static z; + static 0; + static { + (() => { + this["x"] = [seed]; + this["y"] = { seed }; + this["z"] = `${seed}`; + this[0] = [seed]; + })(); + } +} +export class Cls4 { + static accessor x; + static accessor y; + static accessor z; + static accessor 0; + static { + (() => { + this["x"] = [seed]; + this["y"] = { seed }; + this["z"] = `${seed}`; + this[0] = [seed]; + })(); + } +} //// [classStaticPropInitializationInferenceWithElementAccess1.d.ts] @@ -80,3 +145,19 @@ export declare class Cls2 { static accessor z: string; static accessor 0: number[]; } +export declare class Cls3 { + static x: number[]; + static y: { + seed: number; + }; + static z: string; + static 0: number[]; +} +export declare class Cls4 { + static accessor x: number[]; + static accessor y: { + seed: number; + }; + static accessor z: string; + static accessor 0: number[]; +} diff --git a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols index 5a334fac0a319..f311a7957dede 100644 --- a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols +++ b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.symbols @@ -20,9 +20,10 @@ export class Cls1 { >0 : Symbol(Cls1[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 5, 11)) static { - this["x"] = [32]; + this["x"] = [seed]; >this : Symbol(Cls1, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 13)) >"x" : Symbol(Cls1.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 2, 19)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) this["y"] = { seed }; >this : Symbol(Cls1, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 13)) @@ -57,9 +58,10 @@ export class Cls2 { >0 : Symbol(Cls2[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 21, 20)) static { - this["x"] = [32]; + this["x"] = [seed]; >this : Symbol(Cls2, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 16, 1)) >"x" : Symbol(Cls2.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 18, 19)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) this["y"] = { seed }; >this : Symbol(Cls2, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 16, 1)) @@ -77,3 +79,86 @@ export class Cls2 { >seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) } } + +export class Cls3 { +>Cls3 : Symbol(Cls3, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 32, 1)) + + static x; +>x : Symbol(Cls3.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 34, 19)) + + static y; +>y : Symbol(Cls3.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 35, 11)) + + static z; +>z : Symbol(Cls3.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 36, 11)) + + static 0; +>0 : Symbol(Cls3[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 37, 11)) + + static { + (() => { + this["x"] = [seed]; +>this : Symbol(Cls3, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 32, 1)) +>"x" : Symbol(Cls3.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 34, 19)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + this["y"] = { seed }; +>this : Symbol(Cls3, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 32, 1)) +>"y" : Symbol(Cls3.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 35, 11)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 44, 19)) + + this["z"] = `${seed}`; +>this : Symbol(Cls3, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 32, 1)) +>"z" : Symbol(Cls3.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 36, 11)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + this[0] = [seed]; +>this : Symbol(Cls3, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 32, 1)) +>0 : Symbol(Cls3[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 37, 11)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + })(); + } +} + +export class Cls4 { +>Cls4 : Symbol(Cls4, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 50, 1)) + + static accessor x; +>x : Symbol(Cls4.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 52, 19)) + + static accessor y; +>y : Symbol(Cls4.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 53, 20)) + + static accessor z; +>z : Symbol(Cls4.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 54, 20)) + + static accessor 0; +>0 : Symbol(Cls4[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 55, 20)) + + static { + (() => { + this["x"] = [seed]; +>this : Symbol(Cls4, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 50, 1)) +>"x" : Symbol(Cls4.x, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 52, 19)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + this["y"] = { seed }; +>this : Symbol(Cls4, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 50, 1)) +>"y" : Symbol(Cls4.y, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 53, 20)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 62, 19)) + + this["z"] = `${seed}`; +>this : Symbol(Cls4, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 50, 1)) +>"z" : Symbol(Cls4.z, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 54, 20)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + this[0] = [seed]; +>this : Symbol(Cls4, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 50, 1)) +>0 : Symbol(Cls4[0], Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 55, 20)) +>seed : Symbol(seed, Decl(classStaticPropInitializationInferenceWithElementAccess1.ts, 0, 3)) + + })(); + } +} + diff --git a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types index c50e5ccb466d0..a09856b676bd6 100644 --- a/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types +++ b/tests/baselines/reference/classStaticPropInitializationInferenceWithElementAccess1.types @@ -28,19 +28,19 @@ export class Cls1 { > : ^^^^^^^^ static { - this["x"] = [32]; ->this["x"] = [32] : number[] -> : ^^^^^^^^ + this["x"] = [seed]; +>this["x"] = [seed] : number[] +> : ^^^^^^^^ >this["x"] : number[] > : ^^^^^^^^ >this : typeof Cls1 > : ^^^^^^^^^^^ >"x" : "x" > : ^^^ ->[32] : number[] -> : ^^^^^^^^ ->32 : 32 -> : ^^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ this["y"] = { seed }; >this["y"] = { seed } : { seed: number; } @@ -107,19 +107,19 @@ export class Cls2 { > : ^^^^^^^^ static { - this["x"] = [32]; ->this["x"] = [32] : number[] -> : ^^^^^^^^ + this["x"] = [seed]; +>this["x"] = [seed] : number[] +> : ^^^^^^^^ >this["x"] : number[] > : ^^^^^^^^ >this : typeof Cls2 > : ^^^^^^^^^^^ >"x" : "x" > : ^^^ ->[32] : number[] -> : ^^^^^^^^ ->32 : 32 -> : ^^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ this["y"] = { seed }; >this["y"] = { seed } : { seed: number; } @@ -164,3 +164,182 @@ export class Cls2 { > : ^^^^^^ } } + +export class Cls3 { +>Cls3 : Cls3 +> : ^^^^ + + static x; +>x : number[] +> : ^^^^^^^^ + + static y; +>y : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ + + static z; +>z : string +> : ^^^^^^ + + static 0; +>0 : number[] +> : ^^^^^^^^ + + static { + (() => { +>(() => { this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; })() : void +> : ^^^^ +>(() => { this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; }) : () => void +> : ^^^^^^^^^^ +>() => { this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; } : () => void +> : ^^^^^^^^^^ + + this["x"] = [seed]; +>this["x"] = [seed] : number[] +> : ^^^^^^^^ +>this["x"] : number[] +> : ^^^^^^^^ +>this : typeof Cls3 +> : ^^^^^^^^^^^ +>"x" : "x" +> : ^^^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + this["y"] = { seed }; +>this["y"] = { seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this["y"] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this : typeof Cls3 +> : ^^^^^^^^^^^ +>"y" : "y" +> : ^^^ +>{ seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>seed : number +> : ^^^^^^ + + this["z"] = `${seed}`; +>this["z"] = `${seed}` : string +> : ^^^^^^ +>this["z"] : string +> : ^^^^^^ +>this : typeof Cls3 +> : ^^^^^^^^^^^ +>"z" : "z" +> : ^^^ +>`${seed}` : string +> : ^^^^^^ +>seed : number +> : ^^^^^^ + + this[0] = [seed]; +>this[0] = [seed] : number[] +> : ^^^^^^^^ +>this[0] : number[] +> : ^^^^^^^^ +>this : typeof Cls3 +> : ^^^^^^^^^^^ +>0 : 0 +> : ^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + })(); + } +} + +export class Cls4 { +>Cls4 : Cls4 +> : ^^^^ + + static accessor x; +>x : number[] +> : ^^^^^^^^ + + static accessor y; +>y : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ + + static accessor z; +>z : string +> : ^^^^^^ + + static accessor 0; +>0 : number[] +> : ^^^^^^^^ + + static { + (() => { +>(() => { this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; })() : void +> : ^^^^ +>(() => { this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; }) : () => void +> : ^^^^^^^^^^ +>() => { this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; } : () => void +> : ^^^^^^^^^^ + + this["x"] = [seed]; +>this["x"] = [seed] : number[] +> : ^^^^^^^^ +>this["x"] : number[] +> : ^^^^^^^^ +>this : typeof Cls4 +> : ^^^^^^^^^^^ +>"x" : "x" +> : ^^^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + this["y"] = { seed }; +>this["y"] = { seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this["y"] : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>this : typeof Cls4 +> : ^^^^^^^^^^^ +>"y" : "y" +> : ^^^ +>{ seed } : { seed: number; } +> : ^^^^^^^^^^^^^^^^^ +>seed : number +> : ^^^^^^ + + this["z"] = `${seed}`; +>this["z"] = `${seed}` : string +> : ^^^^^^ +>this["z"] : string +> : ^^^^^^ +>this : typeof Cls4 +> : ^^^^^^^^^^^ +>"z" : "z" +> : ^^^ +>`${seed}` : string +> : ^^^^^^ +>seed : number +> : ^^^^^^ + + this[0] = [seed]; +>this[0] = [seed] : number[] +> : ^^^^^^^^ +>this[0] : number[] +> : ^^^^^^^^ +>this : typeof Cls4 +> : ^^^^^^^^^^^ +>0 : 0 +> : ^ +>[seed] : number[] +> : ^^^^^^^^ +>seed : number +> : ^^^^^^ + + })(); + } +} + diff --git a/tests/cases/compiler/classAccessorInitializationInferenceWithElementAccess1.ts b/tests/cases/compiler/classAccessorInitializationInferenceWithElementAccess1.ts index 8f8b891532d7d..59ba81b2890b9 100644 --- a/tests/cases/compiler/classAccessorInitializationInferenceWithElementAccess1.ts +++ b/tests/cases/compiler/classAccessorInitializationInferenceWithElementAccess1.ts @@ -17,3 +17,21 @@ export class Cls { this[0] = [seed]; } } + +export class Cls2 { + accessor x; + accessor y; + accessor z; + + accessor 0; + + constructor(seed: number) { + (() => { + this['x'] = [seed]; + this['y'] = { seed }; + this['z'] = `${seed}`; + + this[0] = [seed]; + })(); + } +} diff --git a/tests/cases/compiler/classAttributeInferenceTemplate.ts b/tests/cases/compiler/classAttributeInferenceTemplate.ts index 95d084c7084c2..20bb47c94d1b6 100644 --- a/tests/cases/compiler/classAttributeInferenceTemplate.ts +++ b/tests/cases/compiler/classAttributeInferenceTemplate.ts @@ -27,3 +27,35 @@ class MyClass2 { const localProperty = `foo-${variable}`; } } + +class MyClass3 { + property; + property2; + + constructor() { + (() => { + const variable = 'something' + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} + +class MyClass4 { + accessor property; + accessor property2; + + constructor() { + (() => { + const variable = 'something' + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} diff --git a/tests/cases/compiler/classAttributeInferenceTemplateJS.ts b/tests/cases/compiler/classAttributeInferenceTemplateJS.ts index e18556f631bbd..f1772e96cb4a9 100644 --- a/tests/cases/compiler/classAttributeInferenceTemplateJS.ts +++ b/tests/cases/compiler/classAttributeInferenceTemplateJS.ts @@ -30,3 +30,35 @@ class MyClass2 { const localProperty = `foo-${variable}`; } } + +class MyClass3 { + property; + property2; + + constructor() { + (() => { + const variable = 'something' + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} + +class MyClass4 { + accessor property; + accessor property2; + + constructor() { + (() => { + const variable = 'something' + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} diff --git a/tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts b/tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts index 7bd1920a7d6dc..e0d0efe2a6d5c 100644 --- a/tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts +++ b/tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts @@ -16,4 +16,22 @@ export class Cls { this[0] = [seed]; } +} + +export class Cls2 { + x; + y; + z; + + 0; + + constructor(seed: number) { + (() => { + this['x'] = [seed]; + this['y'] = { seed }; + this['z'] = `${seed}`; + + this[0] = [seed]; + })(); + } } \ No newline at end of file diff --git a/tests/cases/conformance/classes/classStaticBlock/classStaticPropInferenceTemplate1.ts b/tests/cases/conformance/classes/classStaticBlock/classStaticPropInferenceTemplate1.ts new file mode 100644 index 0000000000000..05827badf9866 --- /dev/null +++ b/tests/cases/conformance/classes/classStaticBlock/classStaticPropInferenceTemplate1.ts @@ -0,0 +1,62 @@ +// @strict: true +// @target: esnext + +class MyClass { + static property; + static property2; + + static { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + } +} + +class MyClass2 { + static accessor property; + static accessor property2; + + static { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + } +} + +class MyClass3 { + static property; + static property2; + + static { + (() => { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} + +class MyClass4 { + static accessor property; + static accessor property2; + + static { + (() => { + const variable = "something"; + + this.property = `foo`; + this.property2 = `foo-${variable}`; + + const localProperty = `foo-${variable}`; + })(); + } +} diff --git a/tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts b/tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts index 49407289767e5..c7bd40e16e649 100644 --- a/tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts +++ b/tests/cases/conformance/classes/classStaticBlock/classStaticPropInitializationInferenceWithElementAccess1.ts @@ -12,7 +12,7 @@ export class Cls1 { static 0; static { - this["x"] = [32]; + this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; @@ -28,10 +28,46 @@ export class Cls2 { static accessor 0; static { - this["x"] = [32]; + this["x"] = [seed]; this["y"] = { seed }; this["z"] = `${seed}`; this[0] = [seed]; } -} \ No newline at end of file +} + +export class Cls3 { + static x; + static y; + static z; + + static 0; + + static { + (() => { + this["x"] = [seed]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + })(); + } +} + +export class Cls4 { + static accessor x; + static accessor y; + static accessor z; + + static accessor 0; + + static { + (() => { + this["x"] = [seed]; + this["y"] = { seed }; + this["z"] = `${seed}`; + + this[0] = [seed]; + })(); + } +} From 3e4b06fa83f724bc1469ccccd156f9aba393dd07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 30 Nov 2024 18:46:33 +0100 Subject: [PATCH 6/8] fixed regression related to optional class fields --- src/compiler/checker.ts | 7 +- ...sOptionalFieldReturnTypeInference1.symbols | 165 ++++++++++++ ...assOptionalFieldReturnTypeInference1.types | 253 ++++++++++++++++++ .../classOptionalFieldReturnTypeInference1.ts | 67 +++++ 4 files changed, 490 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/classOptionalFieldReturnTypeInference1.symbols create mode 100644 tests/baselines/reference/classOptionalFieldReturnTypeInference1.types create mode 100644 tests/cases/compiler/classOptionalFieldReturnTypeInference1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2b68e87d44f96..51cbe22d2b6fc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31620,10 +31620,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const decl = lhsSymbol && lhsSymbol.valueDeclaration; // Unannotated, uninitialized property declarations have a type implied by their usage in the constructor or static blocks. // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case when the assignment declaration is in the respective auto container - if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl)) && (!isAccessExpression(binaryExpression.left) || isThisPropertyAccessInAutoContainer(binaryExpression.left, lhsSymbol))) { + if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl))) { const overallAnnotation = getEffectiveTypeAnnotationNode(decl); - return (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) || + const type = (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) || (isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) : undefined); + if (type || isAccessExpression(binaryExpression.left) && isThisPropertyAccessInAutoContainer(binaryExpression.left, lhsSymbol)) { + return type; + } } if (kind === AssignmentDeclarationKind.None) { return getTypeOfExpression(binaryExpression.left); diff --git a/tests/baselines/reference/classOptionalFieldReturnTypeInference1.symbols b/tests/baselines/reference/classOptionalFieldReturnTypeInference1.symbols new file mode 100644 index 0000000000000..73b40222e785f --- /dev/null +++ b/tests/baselines/reference/classOptionalFieldReturnTypeInference1.symbols @@ -0,0 +1,165 @@ +//// [tests/cases/compiler/classOptionalFieldReturnTypeInference1.ts] //// + +=== classOptionalFieldReturnTypeInference1.ts === +declare abstract class BasePrompt { +>BasePrompt : Symbol(BasePrompt, Decl(classOptionalFieldReturnTypeInference1.ts, 0, 0)) + + choice( +>choice : Symbol(BasePrompt.choice, Decl(classOptionalFieldReturnTypeInference1.ts, 0, 35)) +>Choice : Symbol(Choice, Decl(classOptionalFieldReturnTypeInference1.ts, 1, 9)) +>Result : Symbol(Result, Decl(classOptionalFieldReturnTypeInference1.ts, 1, 31)) +>Choice : Symbol(Choice, Decl(classOptionalFieldReturnTypeInference1.ts, 1, 9)) + + title: string, +>title : Symbol(title, Decl(classOptionalFieldReturnTypeInference1.ts, 1, 61)) + + choices: readonly Choice[], +>choices : Symbol(choices, Decl(classOptionalFieldReturnTypeInference1.ts, 2, 18)) +>Choice : Symbol(Choice, Decl(classOptionalFieldReturnTypeInference1.ts, 1, 9)) + + ): Promise; +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>Result : Symbol(Result, Decl(classOptionalFieldReturnTypeInference1.ts, 1, 31)) +} + +type MiddlewareNode = { +>MiddlewareNode : Symbol(MiddlewareNode, Decl(classOptionalFieldReturnTypeInference1.ts, 5, 1)) + + name?: string; +>name : Symbol(name, Decl(classOptionalFieldReturnTypeInference1.ts, 7, 23)) + +}; + +declare class Codemods { +>Codemods : Symbol(Codemods, Decl(classOptionalFieldReturnTypeInference1.ts, 9, 2)) + + registerMiddleware( +>registerMiddleware : Symbol(Codemods.registerMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 11, 24)) + + stack: "server" | "router" | "named", +>stack : Symbol(stack, Decl(classOptionalFieldReturnTypeInference1.ts, 12, 21)) + + middleware: MiddlewareNode[], +>middleware : Symbol(middleware, Decl(classOptionalFieldReturnTypeInference1.ts, 13, 41)) +>MiddlewareNode : Symbol(MiddlewareNode, Decl(classOptionalFieldReturnTypeInference1.ts, 5, 1)) + + ): Promise; +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +} + +declare class BaseCommand { +>BaseCommand : Symbol(BaseCommand, Decl(classOptionalFieldReturnTypeInference1.ts, 16, 1)) + + prompt: BasePrompt; +>prompt : Symbol(BaseCommand.prompt, Decl(classOptionalFieldReturnTypeInference1.ts, 18, 27)) +>BasePrompt : Symbol(BasePrompt, Decl(classOptionalFieldReturnTypeInference1.ts, 0, 0)) + + createCodemods(): Promise; +>createCodemods : Symbol(BaseCommand.createCodemods, Decl(classOptionalFieldReturnTypeInference1.ts, 19, 21)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>Codemods : Symbol(Codemods, Decl(classOptionalFieldReturnTypeInference1.ts, 9, 2)) +} + +export default class MakeMiddleware extends BaseCommand { +>MakeMiddleware : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>BaseCommand : Symbol(BaseCommand, Decl(classOptionalFieldReturnTypeInference1.ts, 16, 1)) + + declare name: string; +>name : Symbol(MakeMiddleware.name, Decl(classOptionalFieldReturnTypeInference1.ts, 23, 57)) + + declare stack?: "server" | "named" | "router"; +>stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) + + + async run() { +>run : Symbol(MakeMiddleware.run, Decl(classOptionalFieldReturnTypeInference1.ts, 26, 48)) + + const stackChoices = ["server", "router", "named"]; +>stackChoices : Symbol(stackChoices, Decl(classOptionalFieldReturnTypeInference1.ts, 30, 9)) + + if (!this.stack) { +>this.stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) +>this : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) + + this.stack = await this.prompt.choice( +>this.stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) +>this : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) +>this.prompt.choice : Symbol(BasePrompt.choice, Decl(classOptionalFieldReturnTypeInference1.ts, 0, 35)) +>this.prompt : Symbol(BaseCommand.prompt, Decl(classOptionalFieldReturnTypeInference1.ts, 18, 27)) +>this : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>prompt : Symbol(BaseCommand.prompt, Decl(classOptionalFieldReturnTypeInference1.ts, 18, 27)) +>choice : Symbol(BasePrompt.choice, Decl(classOptionalFieldReturnTypeInference1.ts, 0, 35)) + + "Under which stack you want to register the middleware?", + stackChoices, +>stackChoices : Symbol(stackChoices, Decl(classOptionalFieldReturnTypeInference1.ts, 30, 9)) + + ); + } + + if (!stackChoices.includes(this.stack)) { +>stackChoices.includes : Symbol(Array.includes, Decl(lib.es2016.array.include.d.ts, --, --)) +>stackChoices : Symbol(stackChoices, Decl(classOptionalFieldReturnTypeInference1.ts, 30, 9)) +>includes : Symbol(Array.includes, Decl(lib.es2016.array.include.d.ts, --, --)) +>this.stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) +>this : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) + + return; + } + + const codemods = await this.createCodemods(); +>codemods : Symbol(codemods, Decl(classOptionalFieldReturnTypeInference1.ts, 43, 9)) +>this.createCodemods : Symbol(BaseCommand.createCodemods, Decl(classOptionalFieldReturnTypeInference1.ts, 19, 21)) +>this : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>createCodemods : Symbol(BaseCommand.createCodemods, Decl(classOptionalFieldReturnTypeInference1.ts, 19, 21)) + + await codemods.registerMiddleware(this.stack, [ +>codemods.registerMiddleware : Symbol(Codemods.registerMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 11, 24)) +>codemods : Symbol(codemods, Decl(classOptionalFieldReturnTypeInference1.ts, 43, 9)) +>registerMiddleware : Symbol(Codemods.registerMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 11, 24)) +>this.stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) +>this : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>stack : Symbol(MakeMiddleware.stack, Decl(classOptionalFieldReturnTypeInference1.ts, 24, 23)) + { + name: this.name, +>name : Symbol(name, Decl(classOptionalFieldReturnTypeInference1.ts, 46, 7)) +>this.name : Symbol(MakeMiddleware.name, Decl(classOptionalFieldReturnTypeInference1.ts, 23, 57)) +>this : Symbol(MakeMiddleware, Decl(classOptionalFieldReturnTypeInference1.ts, 21, 1)) +>name : Symbol(MakeMiddleware.name, Decl(classOptionalFieldReturnTypeInference1.ts, 23, 57)) + + }, + ]); + } +} + +declare function dom$(description: string): T; +>dom$ : Symbol(dom$, Decl(classOptionalFieldReturnTypeInference1.ts, 51, 1)) +>T : Symbol(T, Decl(classOptionalFieldReturnTypeInference1.ts, 53, 22)) +>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>description : Symbol(description, Decl(classOptionalFieldReturnTypeInference1.ts, 53, 45)) +>T : Symbol(T, Decl(classOptionalFieldReturnTypeInference1.ts, 53, 22)) + +export abstract class PeekViewWidget { +>PeekViewWidget : Symbol(PeekViewWidget, Decl(classOptionalFieldReturnTypeInference1.ts, 53, 69)) + + protected _titleElement?: HTMLDivElement; +>_titleElement : Symbol(PeekViewWidget._titleElement, Decl(classOptionalFieldReturnTypeInference1.ts, 55, 38)) +>HTMLDivElement : Symbol(HTMLDivElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + protected _fillHead(container: HTMLElement, noCloseAction?: boolean): void { +>_fillHead : Symbol(PeekViewWidget._fillHead, Decl(classOptionalFieldReturnTypeInference1.ts, 56, 43)) +>container : Symbol(container, Decl(classOptionalFieldReturnTypeInference1.ts, 58, 22)) +>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) +>noCloseAction : Symbol(noCloseAction, Decl(classOptionalFieldReturnTypeInference1.ts, 58, 45)) + + this._titleElement = dom$(".peekview-title"); +>this._titleElement : Symbol(PeekViewWidget._titleElement, Decl(classOptionalFieldReturnTypeInference1.ts, 55, 38)) +>this : Symbol(PeekViewWidget, Decl(classOptionalFieldReturnTypeInference1.ts, 53, 69)) +>_titleElement : Symbol(PeekViewWidget._titleElement, Decl(classOptionalFieldReturnTypeInference1.ts, 55, 38)) +>dom$ : Symbol(dom$, Decl(classOptionalFieldReturnTypeInference1.ts, 51, 1)) + } +} + diff --git a/tests/baselines/reference/classOptionalFieldReturnTypeInference1.types b/tests/baselines/reference/classOptionalFieldReturnTypeInference1.types new file mode 100644 index 0000000000000..574a42b8d2612 --- /dev/null +++ b/tests/baselines/reference/classOptionalFieldReturnTypeInference1.types @@ -0,0 +1,253 @@ +//// [tests/cases/compiler/classOptionalFieldReturnTypeInference1.ts] //// + +=== classOptionalFieldReturnTypeInference1.ts === +declare abstract class BasePrompt { +>BasePrompt : BasePrompt +> : ^^^^^^^^^^ + + choice( +>choice : (title: string, choices: readonly Choice[]) => Promise +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + title: string, +>title : string +> : ^^^^^^ + + choices: readonly Choice[], +>choices : readonly Choice[] +> : ^^^^^^^^^^^^^^^^^ + + ): Promise; +} + +type MiddlewareNode = { +>MiddlewareNode : MiddlewareNode +> : ^^^^^^^^^^^^^^ + + name?: string; +>name : string | undefined +> : ^^^^^^^^^^^^^^^^^^ + +}; + +declare class Codemods { +>Codemods : Codemods +> : ^^^^^^^^ + + registerMiddleware( +>registerMiddleware : (stack: "server" | "router" | "named", middleware: MiddlewareNode[]) => Promise +> : ^ ^^ ^^ ^^ ^^^^^ + + stack: "server" | "router" | "named", +>stack : "server" | "router" | "named" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + middleware: MiddlewareNode[], +>middleware : MiddlewareNode[] +> : ^^^^^^^^^^^^^^^^ + + ): Promise; +} + +declare class BaseCommand { +>BaseCommand : BaseCommand +> : ^^^^^^^^^^^ + + prompt: BasePrompt; +>prompt : BasePrompt +> : ^^^^^^^^^^ + + createCodemods(): Promise; +>createCodemods : () => Promise +> : ^^^^^^ +} + +export default class MakeMiddleware extends BaseCommand { +>MakeMiddleware : MakeMiddleware +> : ^^^^^^^^^^^^^^ +>BaseCommand : BaseCommand +> : ^^^^^^^^^^^ + + declare name: string; +>name : string +> : ^^^^^^ + + declare stack?: "server" | "named" | "router"; +>stack : "server" | "router" | "named" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + + async run() { +>run : () => Promise +> : ^^^^^^^^^^^^^^^^^^^ + + const stackChoices = ["server", "router", "named"]; +>stackChoices : string[] +> : ^^^^^^^^ +>["server", "router", "named"] : string[] +> : ^^^^^^^^ +>"server" : "server" +> : ^^^^^^^^ +>"router" : "router" +> : ^^^^^^^^ +>"named" : "named" +> : ^^^^^^^ + + if (!this.stack) { +>!this.stack : boolean +> : ^^^^^^^ +>this.stack : "server" | "router" | "named" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this : this +> : ^^^^ +>stack : "server" | "router" | "named" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + this.stack = await this.prompt.choice( +>this.stack = await this.prompt.choice( "Under which stack you want to register the middleware?", stackChoices, ) : "server" | "router" | "named" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.stack : "server" | "router" | "named" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this : this +> : ^^^^ +>stack : "server" | "router" | "named" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>await this.prompt.choice( "Under which stack you want to register the middleware?", stackChoices, ) : "server" | "router" | "named" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.prompt.choice( "Under which stack you want to register the middleware?", stackChoices, ) : Promise<"server" | "router" | "named"> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.prompt.choice : (title: string, choices: readonly Choice[]) => Promise +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>this.prompt : BasePrompt +> : ^^^^^^^^^^ +>this : this +> : ^^^^ +>prompt : BasePrompt +> : ^^^^^^^^^^ +>choice : (title: string, choices: readonly Choice[]) => Promise +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + "Under which stack you want to register the middleware?", +>"Under which stack you want to register the middleware?" : "Under which stack you want to register the middleware?" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + stackChoices, +>stackChoices : string[] +> : ^^^^^^^^ + + ); + } + + if (!stackChoices.includes(this.stack)) { +>!stackChoices.includes(this.stack) : boolean +> : ^^^^^^^ +>stackChoices.includes(this.stack) : boolean +> : ^^^^^^^ +>stackChoices.includes : (searchElement: string, fromIndex?: number) => boolean +> : ^ ^^^^^^^^^^ ^^^ ^^^^^ +>stackChoices : string[] +> : ^^^^^^^^ +>includes : (searchElement: string, fromIndex?: number) => boolean +> : ^ ^^^^^^^^^^ ^^^ ^^^^^ +>this.stack : "server" | "router" | "named" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this : this +> : ^^^^ +>stack : "server" | "router" | "named" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + return; + } + + const codemods = await this.createCodemods(); +>codemods : Codemods +> : ^^^^^^^^ +>await this.createCodemods() : Codemods +> : ^^^^^^^^ +>this.createCodemods() : Promise +> : ^^^^^^^^^^^^^^^^^ +>this.createCodemods : () => Promise +> : ^^^^^^ +>this : this +> : ^^^^ +>createCodemods : () => Promise +> : ^^^^^^ + + await codemods.registerMiddleware(this.stack, [ +>await codemods.registerMiddleware(this.stack, [ { name: this.name, }, ]) : void +> : ^^^^ +>codemods.registerMiddleware(this.stack, [ { name: this.name, }, ]) : Promise +> : ^^^^^^^^^^^^^ +>codemods.registerMiddleware : (stack: "server" | "router" | "named", middleware: MiddlewareNode[]) => Promise +> : ^ ^^ ^^ ^^ ^^^^^ +>codemods : Codemods +> : ^^^^^^^^ +>registerMiddleware : (stack: "server" | "router" | "named", middleware: MiddlewareNode[]) => Promise +> : ^ ^^ ^^ ^^ ^^^^^ +>this.stack : "server" | "router" | "named" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this : this +> : ^^^^ +>stack : "server" | "router" | "named" +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>[ { name: this.name, }, ] : { name: string; }[] +> : ^^^^^^^^^^^^^^^^^^^ + { +>{ name: this.name, } : { name: string; } +> : ^^^^^^^^^^^^^^^^^ + + name: this.name, +>name : string +> : ^^^^^^ +>this.name : string +> : ^^^^^^ +>this : this +> : ^^^^ +>name : string +> : ^^^^^^ + + }, + ]); + } +} + +declare function dom$(description: string): T; +>dom$ : (description: string) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>description : string +> : ^^^^^^ + +export abstract class PeekViewWidget { +>PeekViewWidget : PeekViewWidget +> : ^^^^^^^^^^^^^^ + + protected _titleElement?: HTMLDivElement; +>_titleElement : HTMLDivElement | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + protected _fillHead(container: HTMLElement, noCloseAction?: boolean): void { +>_fillHead : (container: HTMLElement, noCloseAction?: boolean) => void +> : ^ ^^ ^^ ^^^ ^^^^^ +>container : HTMLElement +> : ^^^^^^^^^^^ +>noCloseAction : boolean | undefined +> : ^^^^^^^^^^^^^^^^^^^ + + this._titleElement = dom$(".peekview-title"); +>this._titleElement = dom$(".peekview-title") : HTMLDivElement +> : ^^^^^^^^^^^^^^ +>this._titleElement : HTMLDivElement | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this : this +> : ^^^^ +>_titleElement : HTMLDivElement | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>dom$(".peekview-title") : HTMLDivElement +> : ^^^^^^^^^^^^^^ +>dom$ : (description: string) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>".peekview-title" : ".peekview-title" +> : ^^^^^^^^^^^^^^^^^ + } +} + diff --git a/tests/cases/compiler/classOptionalFieldReturnTypeInference1.ts b/tests/cases/compiler/classOptionalFieldReturnTypeInference1.ts new file mode 100644 index 0000000000000..bd72fefed7580 --- /dev/null +++ b/tests/cases/compiler/classOptionalFieldReturnTypeInference1.ts @@ -0,0 +1,67 @@ +// @strict: true +// @target: esnext +// @lib: esnext,dom +// @noEmit: true + +declare abstract class BasePrompt { + choice( + title: string, + choices: readonly Choice[], + ): Promise; +} + +type MiddlewareNode = { + name?: string; +}; + +declare class Codemods { + registerMiddleware( + stack: "server" | "router" | "named", + middleware: MiddlewareNode[], + ): Promise; +} + +declare class BaseCommand { + prompt: BasePrompt; + createCodemods(): Promise; +} + +export default class MakeMiddleware extends BaseCommand { + declare name: string; + + declare stack?: "server" | "named" | "router"; + + + async run() { + const stackChoices = ["server", "router", "named"]; + + if (!this.stack) { + this.stack = await this.prompt.choice( + "Under which stack you want to register the middleware?", + stackChoices, + ); + } + + if (!stackChoices.includes(this.stack)) { + return; + } + + const codemods = await this.createCodemods(); + + await codemods.registerMiddleware(this.stack, [ + { + name: this.name, + }, + ]); + } +} + +declare function dom$(description: string): T; + +export abstract class PeekViewWidget { + protected _titleElement?: HTMLDivElement; + + protected _fillHead(container: HTMLElement, noCloseAction?: boolean): void { + this._titleElement = dom$(".peekview-title"); + } +} From db429aa337d4b0dec10b75117c3b6335a8b90a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 30 Nov 2024 20:28:54 +0100 Subject: [PATCH 7/8] correct auto container lookup --- src/compiler/checker.ts | 12 ++- ...tualTypingOutsideOfConstructor1.errors.txt | 24 ++++- ...textualTypingOutsideOfConstructor1.symbols | 84 ++++++++++++----- ...ontextualTypingOutsideOfConstructor1.types | 90 +++++++++++++++++++ ...tualTypingOutsideOfStaticBlock1.errors.txt | 24 ++++- ...textualTypingOutsideOfStaticBlock1.symbols | 84 ++++++++++++----- ...ontextualTypingOutsideOfStaticBlock1.types | 90 +++++++++++++++++++ ...ceContextualTypingOutsideOfConstructor1.ts | 10 +++ ...ceContextualTypingOutsideOfStaticBlock1.ts | 10 +++ 9 files changed, 372 insertions(+), 56 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51cbe22d2b6fc..f06353eb80048 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11366,14 +11366,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isThisProperty(node) || !isAutoTypedProperty(prop)) { return false; } - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); - return isClassStaticBlockDeclaration(thisContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent; + const autoContainer = getAutoContainer(node); + return isClassStaticBlockDeclaration(autoContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === autoContainer.parent; } if (!isConstructorDeclaredProperty(prop) && (!isThisProperty(node) || !isAutoTypedProperty(prop))) { return false; } - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); - return isConstructorDeclaration(thisContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === thisContainer.parent || thisContainer === getDeclaringConstructor(prop); + const autoContainer = getAutoContainer(node); + return isConstructorDeclaration(autoContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === autoContainer.parent || autoContainer === getDeclaringConstructor(prop); + } + + function getAutoContainer(node: Node) { + return findAncestor(node.parent, node => !!getContainingFunctionOrClassStaticBlock(node) && !getImmediatelyInvokedFunctionExpression(node))!; } function getDeclaringConstructor(symbol: Symbol) { diff --git a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt index 24c4793121ee2..f1ea3b9565779 100644 --- a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt +++ b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.errors.txt @@ -1,8 +1,10 @@ -classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(16,20): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? -classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(29,20): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(15,22): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(21,20): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(33,22): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(39,20): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? -==== classAttributeInferenceContextualTypingOutsideOfConstructor1.ts (2 errors) ==== +==== classAttributeInferenceContextualTypingOutsideOfConstructor1.ts (4 errors) ==== // https://github.com/microsoft/TypeScript/issues/60394 type State = { type: "running"; speed: number } | { type: "stopped" }; @@ -14,6 +16,14 @@ classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(29,20): error TS constructor() { this.state = initialState; + + const localRun = (speed: number) => { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classAttributeInferenceContextualTypingOutsideOfConstructor1.ts:3:16: The expected type comes from property 'type' which is declared here on type 'State' + } } run(speed: number) { @@ -30,6 +40,14 @@ classAttributeInferenceContextualTypingOutsideOfConstructor1.ts(29,20): error TS constructor() { this.state = initialState; + + const localRun = (speed: number) => { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classAttributeInferenceContextualTypingOutsideOfConstructor1.ts:3:16: The expected type comes from property 'type' which is declared here on type 'State' + } } run(speed: number) { diff --git a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols index 5c21d3a3caa33..85383243a00ff 100644 --- a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols +++ b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.symbols @@ -25,59 +25,97 @@ class Actor1 { >this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) >state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) >initialState : Symbol(initialState, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 13)) + + const localRun = (speed: number) => { +>localRun : Symbol(localRun, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 12, 9)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 12, 22)) + + this.state = { type: "running", speed }; +>this.state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) +>state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 13, 20)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 13, 37)) + + this.state = { type: "runnnning", speed }; // error +>this.state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) +>state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 14, 20)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 14, 39)) + } } run(speed: number) { ->run : Symbol(Actor1.run, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 11, 3)) ->speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 13, 6)) +>run : Symbol(Actor1.run, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 16, 3)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 18, 6)) this.state = { type: "running", speed }; >this.state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) >this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) >state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) ->type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 14, 18)) ->speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 14, 35)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 35)) this.state = { type: "runnnning", speed }; // error >this.state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) >this : Symbol(Actor1, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 34)) >state : Symbol(Actor1.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 6, 14)) ->type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 15, 18)) ->speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 15, 37)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 20, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 20, 37)) } } class Actor2 { ->Actor2 : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) +>Actor2 : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 22, 1)) accessor state; ->state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) constructor() { this.state = initialState; ->this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) ->this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) ->state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 22, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) >initialState : Symbol(initialState, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 4, 13)) + + const localRun = (speed: number) => { +>localRun : Symbol(localRun, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 30, 9)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 30, 22)) + + this.state = { type: "running", speed }; +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 22, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 31, 20)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 31, 37)) + + this.state = { type: "runnnning", speed }; // error +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 22, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 32, 20)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 32, 39)) + } } run(speed: number) { ->run : Symbol(Actor2.run, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 3)) ->speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 26, 6)) +>run : Symbol(Actor2.run, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 34, 3)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 36, 6)) this.state = { type: "running", speed }; ->this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) ->this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) ->state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) ->type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 27, 18)) ->speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 27, 35)) +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 22, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 37, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 37, 35)) this.state = { type: "runnnning", speed }; // error ->this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) ->this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 17, 1)) ->state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 19, 14)) ->type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 28, 18)) ->speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 28, 37)) +>this.state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>this : Symbol(Actor2, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 22, 1)) +>state : Symbol(Actor2.state, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 24, 14)) +>type : Symbol(type, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 38, 18)) +>speed : Symbol(speed, Decl(classAttributeInferenceContextualTypingOutsideOfConstructor1.ts, 38, 37)) } } diff --git a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types index 343b5a56045e6..8550cde340dd3 100644 --- a/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types +++ b/tests/baselines/reference/classAttributeInferenceContextualTypingOutsideOfConstructor1.types @@ -37,6 +37,51 @@ class Actor1 { > : ^^^^^ >initialState : State > : ^^^^^ + + const localRun = (speed: number) => { +>localRun : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>(speed: number) => { this.state = { type: "running", speed }; this.state = { type: "runnnning", speed }; // error } : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "running", speed }; +>this.state = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "runnnning", speed }; // error +>this.state = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } } run(speed: number) { @@ -103,6 +148,51 @@ class Actor2 { > : ^^^^^ >initialState : State > : ^^^^^ + + const localRun = (speed: number) => { +>localRun : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>(speed: number) => { this.state = { type: "running", speed }; this.state = { type: "runnnning", speed }; // error } : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "running", speed }; +>this.state = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.state = { type: "runnnning", speed }; // error +>this.state = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.state : State +> : ^^^^^ +>this : this +> : ^^^^ +>state : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } } run(speed: number) { diff --git a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt index 0a3d38bf568c5..0443c1907e4b3 100644 --- a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt +++ b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.errors.txt @@ -1,8 +1,10 @@ -classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(14,27): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? -classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(27,27): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(13,29): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(19,27): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(31,29): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(37,27): error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? -==== classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts (2 errors) ==== +==== classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts (4 errors) ==== type State = { type: "running"; speed: number } | { type: "stopped" }; declare const initialState: State; @@ -12,6 +14,14 @@ classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(27,27): error static { this.initialState = initialState; + + const localSetAsInitiallyRunning = (speed: number) => { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts:1:16: The expected type comes from property 'type' which is declared here on type 'State' + } } static setAsInitiallyRunning(speed: number) { @@ -28,6 +38,14 @@ classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts(27,27): error static { this.initialState = initialState; + + const localSetAsInitiallyRunning = (speed: number) => { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + ~~~~ +!!! error TS2820: Type '"runnnning"' is not assignable to type '"running" | "stopped"'. Did you mean '"running"'? +!!! related TS6500 classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts:1:16: The expected type comes from property 'type' which is declared here on type 'State' + } } static setAsInitiallyRunning(speed: number) { diff --git a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols index 1a8613c38ba66..eee588fbe4c80 100644 --- a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols +++ b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.symbols @@ -23,59 +23,97 @@ class Actor1 { >this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) >initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) >initialState : Symbol(initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 13)) + + const localSetAsInitiallyRunning = (speed: number) => { +>localSetAsInitiallyRunning : Symbol(localSetAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 10, 9)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 10, 40)) + + this.initialState = { type: "running", speed }; +>this.initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) +>initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 11, 27)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 11, 44)) + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) +>initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 12, 27)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 12, 46)) + } } static setAsInitiallyRunning(speed: number) { ->setAsInitiallyRunning : Symbol(Actor1.setAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 9, 3)) ->speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 11, 31)) +>setAsInitiallyRunning : Symbol(Actor1.setAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 14, 3)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 16, 31)) this.initialState = { type: "running", speed }; >this.initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) >this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) >initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) ->type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 12, 25)) ->speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 12, 42)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 42)) this.initialState = { type: "runnnning", speed }; // error >this.initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) >this : Symbol(Actor1, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 34)) >initialState : Symbol(Actor1.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 4, 14)) ->type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 13, 25)) ->speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 13, 44)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 18, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 18, 44)) } } class Actor2 { ->Actor2 : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) +>Actor2 : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 20, 1)) static accessor initialState; ->initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) static { this.initialState = initialState; ->this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) ->this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) ->initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 20, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) >initialState : Symbol(initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 2, 13)) + + const localSetAsInitiallyRunning = (speed: number) => { +>localSetAsInitiallyRunning : Symbol(localSetAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 28, 9)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 28, 40)) + + this.initialState = { type: "running", speed }; +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 20, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 29, 27)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 29, 44)) + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 20, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 30, 27)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 30, 46)) + } } static setAsInitiallyRunning(speed: number) { ->setAsInitiallyRunning : Symbol(Actor2.setAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 3)) ->speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 24, 31)) +>setAsInitiallyRunning : Symbol(Actor2.setAsInitiallyRunning, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 32, 3)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 34, 31)) this.initialState = { type: "running", speed }; ->this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) ->this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) ->initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) ->type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 25, 25)) ->speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 25, 42)) +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 20, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 35, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 35, 42)) this.initialState = { type: "runnnning", speed }; // error ->this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) ->this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 15, 1)) ->initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 17, 14)) ->type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 26, 25)) ->speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 26, 44)) +>this.initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>this : Symbol(Actor2, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 20, 1)) +>initialState : Symbol(Actor2.initialState, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 22, 14)) +>type : Symbol(type, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 36, 25)) +>speed : Symbol(speed, Decl(classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts, 36, 44)) } } diff --git a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types index 83c2a7b549518..e69fa951fd309 100644 --- a/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types +++ b/tests/baselines/reference/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.types @@ -35,6 +35,51 @@ class Actor1 { > : ^^^^^ >initialState : State > : ^^^^^ + + const localSetAsInitiallyRunning = (speed: number) => { +>localSetAsInitiallyRunning : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>(speed: number) => { this.initialState = { type: "running", speed }; this.initialState = { type: "runnnning", speed }; // error } : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "running", speed }; +>this.initialState = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor1 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor1 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } } static setAsInitiallyRunning(speed: number) { @@ -101,6 +146,51 @@ class Actor2 { > : ^^^^^ >initialState : State > : ^^^^^ + + const localSetAsInitiallyRunning = (speed: number) => { +>localSetAsInitiallyRunning : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>(speed: number) => { this.initialState = { type: "running", speed }; this.initialState = { type: "runnnning", speed }; // error } : (speed: number) => void +> : ^ ^^ ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "running", speed }; +>this.initialState = { type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor2 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "running", speed } : { type: "running"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "running" +> : ^^^^^^^^^ +>"running" : "running" +> : ^^^^^^^^^ +>speed : number +> : ^^^^^^ + + this.initialState = { type: "runnnning", speed }; // error +>this.initialState = { type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.initialState : State +> : ^^^^^ +>this : typeof Actor2 +> : ^^^^^^^^^^^^^ +>initialState : State +> : ^^^^^ +>{ type: "runnnning", speed } : { type: "runnnning"; speed: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>type : "runnnning" +> : ^^^^^^^^^^^ +>"runnnning" : "runnnning" +> : ^^^^^^^^^^^ +>speed : number +> : ^^^^^^ + } } static setAsInitiallyRunning(speed: number) { diff --git a/tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts b/tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts index c1f570b26410c..7843d8c9b6687 100644 --- a/tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts +++ b/tests/cases/compiler/classAttributeInferenceContextualTypingOutsideOfConstructor1.ts @@ -13,6 +13,11 @@ class Actor1 { constructor() { this.state = initialState; + + const localRun = (speed: number) => { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + } } run(speed: number) { @@ -26,6 +31,11 @@ class Actor2 { constructor() { this.state = initialState; + + const localRun = (speed: number) => { + this.state = { type: "running", speed }; + this.state = { type: "runnnning", speed }; // error + } } run(speed: number) { diff --git a/tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts b/tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts index 89b1def5c3dd5..df4e9dbd594f3 100644 --- a/tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts +++ b/tests/cases/conformance/classes/classStaticBlock/classStaticFieldInferenceContextualTypingOutsideOfStaticBlock1.ts @@ -11,6 +11,11 @@ class Actor1 { static { this.initialState = initialState; + + const localSetAsInitiallyRunning = (speed: number) => { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + } } static setAsInitiallyRunning(speed: number) { @@ -24,6 +29,11 @@ class Actor2 { static { this.initialState = initialState; + + const localSetAsInitiallyRunning = (speed: number) => { + this.initialState = { type: "running", speed }; + this.initialState = { type: "runnnning", speed }; // error + } } static setAsInitiallyRunning(speed: number) { From c1a84394d33df3aec497351441aab1bcdd29619a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 30 Nov 2024 21:43:00 +0100 Subject: [PATCH 8/8] actually fix it fix it --- src/compiler/checker.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f06353eb80048..da6554ea83369 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11366,18 +11366,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isThisProperty(node) || !isAutoTypedProperty(prop)) { return false; } - const autoContainer = getAutoContainer(node); + const autoContainer = getAutoContainer(node)!; return isClassStaticBlockDeclaration(autoContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === autoContainer.parent; } if (!isConstructorDeclaredProperty(prop) && (!isThisProperty(node) || !isAutoTypedProperty(prop))) { return false; } - const autoContainer = getAutoContainer(node); + const autoContainer = getAutoContainer(node)!; return isConstructorDeclaration(autoContainer) && (prop.parent && getClassLikeDeclarationOfSymbol(prop.parent)) === autoContainer.parent || autoContainer === getDeclaringConstructor(prop); } function getAutoContainer(node: Node) { - return findAncestor(node.parent, node => !!getContainingFunctionOrClassStaticBlock(node) && !getImmediatelyInvokedFunctionExpression(node))!; + let container = getContainingFunctionOrClassStaticBlock(node); + while (container) { + if (getImmediatelyInvokedFunctionExpression(container)) { + container = getContainingFunctionOrClassStaticBlock(container); + continue; + } + return container; + } } function getDeclaringConstructor(symbol: Symbol) {