Allow auto accessor types to be inferred from their flow types in constructors and static blocks (#59732)

Co-authored-by: Ron Buckton <ron.buckton@microsoft.com>
This commit is contained in:
Mateusz Burzyński 2024-10-16 02:52:12 +02:00 коммит произвёл GitHub
Родитель 3b0dfaa73c
Коммит 03c5a37cfb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
28 изменённых файлов: 1314 добавлений и 12 удалений

Просмотреть файл

@ -12005,7 +12005,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
getAnnotatedAccessorType(setter) ||
getAnnotatedAccessorType(accessor) ||
getter && getter.body && getReturnTypeFromBody(getter) ||
accessor && accessor.initializer && getWidenedTypeForVariableLikeDeclaration(accessor, /*reportErrors*/ true);
accessor && getWidenedTypeForVariableLikeDeclaration(accessor, /*reportErrors*/ true);
if (!type) {
if (setter && !isPrivateWithinAmbient(setter)) {
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));

Просмотреть файл

@ -0,0 +1,45 @@
//// [tests/cases/compiler/classAccessorInitializationInferenceWithElementAccess1.ts] ////
//// [classAccessorInitializationInferenceWithElementAccess1.ts]
export class Cls {
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]
export class Cls {
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]
export declare class Cls {
accessor x: number[];
accessor y: {
seed: number;
};
accessor z: string;
accessor 0: number[];
constructor(seed: number);
}

Просмотреть файл

@ -0,0 +1,43 @@
//// [tests/cases/compiler/classAccessorInitializationInferenceWithElementAccess1.ts] ////
=== classAccessorInitializationInferenceWithElementAccess1.ts ===
export class Cls {
>Cls : Symbol(Cls, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 0, 0))
accessor x;
>x : Symbol(Cls.x, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 0, 18))
accessor y;
>y : Symbol(Cls.y, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 1, 15))
accessor z;
>z : Symbol(Cls.z, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 2, 15))
accessor 0;
>0 : Symbol(Cls[0], Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 3, 15))
constructor(seed: number) {
>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 7, 16))
this['x'] = [seed];
>this : Symbol(Cls, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 0, 0))
>'x' : Symbol(Cls.x, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 0, 18))
>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 7, 16))
this['y'] = { seed };
>this : Symbol(Cls, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 0, 0))
>'y' : Symbol(Cls.y, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 1, 15))
>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 9, 21))
this['z'] = `${seed}`;
>this : Symbol(Cls, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 0, 0))
>'z' : Symbol(Cls.z, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 2, 15))
>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 7, 16))
this[0] = [seed];
>this : Symbol(Cls, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 0, 0))
>0 : Symbol(Cls[0], Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 3, 15))
>seed : Symbol(seed, Decl(classAccessorInitializationInferenceWithElementAccess1.ts, 7, 16))
}
}

Просмотреть файл

@ -0,0 +1,85 @@
//// [tests/cases/compiler/classAccessorInitializationInferenceWithElementAccess1.ts] ////
=== classAccessorInitializationInferenceWithElementAccess1.ts ===
export class Cls {
>Cls : Cls
> : ^^^
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['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
> : ^^^^^^
}
}

Просмотреть файл

@ -13,16 +13,42 @@ class MyClass {
const localProperty = `foo-${variable}`; // Correctly inferred as `string`
}
}
}
class MyClass2 {
accessor property;
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`
}
}
//// [classAttributeInferenceTemplate.js]
"use strict";
var MyClass = /** @class */ (function () {
function MyClass() {
var variable = 'something';
this.property = "foo"; // Correctly inferred as `string`
this.property2 = "foo-".concat(variable); // Causes an error
var localProperty = "foo-".concat(variable); // Correctly inferred as `string`
class MyClass {
property;
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`
}
return MyClass;
}());
}
class MyClass2 {
accessor property;
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`
}
}

Просмотреть файл

@ -30,3 +30,34 @@ class MyClass {
>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 5, 13))
}
}
class MyClass2 {
>MyClass2 : Symbol(MyClass2, Decl(classAttributeInferenceTemplate.ts, 12, 1))
accessor property;
>property : Symbol(MyClass2.property, Decl(classAttributeInferenceTemplate.ts, 14, 16))
accessor property2;
>property2 : Symbol(MyClass2.property2, Decl(classAttributeInferenceTemplate.ts, 15, 22))
constructor() {
const variable = 'something'
>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 19, 13))
this.property = `foo`; // Correctly inferred as `string`
>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 : 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`
>localProperty : Symbol(localProperty, Decl(classAttributeInferenceTemplate.ts, 24, 13))
>variable : Symbol(variable, Decl(classAttributeInferenceTemplate.ts, 19, 13))
}
}

Просмотреть файл

@ -55,3 +55,59 @@ class MyClass {
> : ^^^^^^^^^^^
}
}
class MyClass2 {
>MyClass2 : MyClass2
> : ^^^^^^^^
accessor property;
>property : string
> : ^^^^^^
accessor property2;
>property2 : string
> : ^^^^^^
constructor() {
const variable = 'something'
>variable : "something"
> : ^^^^^^^^^^^
>'something' : "something"
> : ^^^^^^^^^^^
this.property = `foo`; // Correctly inferred as `string`
>this.property = `foo` : "foo"
> : ^^^^^
>this.property : string
> : ^^^^^^
>this : this
> : ^^^^
>property : string
> : ^^^^^^
>`foo` : "foo"
> : ^^^^^
this.property2 = `foo-${variable}`; // Causes an error
>this.property2 = `foo-${variable}` : "foo-something"
> : ^^^^^^^^^^^^^^^
>this.property2 : string
> : ^^^^^^
>this : this
> : ^^^^
>property2 : string
> : ^^^^^^
>`foo-${variable}` : "foo-something"
> : ^^^^^^^^^^^^^^^
>variable : "something"
> : ^^^^^^^^^^^
const localProperty = `foo-${variable}`; // Correctly inferred as `string`
>localProperty : "foo-something"
> : ^^^^^^^^^^^^^^^
>`foo-${variable}` : "foo-something"
> : ^^^^^^^^^^^^^^^
>variable : "something"
> : ^^^^^^^^^^^
}
}

Просмотреть файл

@ -30,3 +30,34 @@ class MyClass {
>variable : Symbol(variable, Decl(index.js, 5, 13))
}
}
class MyClass2 {
>MyClass2 : Symbol(MyClass2, Decl(index.js, 12, 1))
accessor property;
>property : Symbol(MyClass2.property, Decl(index.js, 14, 16))
accessor property2;
>property2 : Symbol(MyClass2.property2, Decl(index.js, 15, 22))
constructor() {
const variable = 'something'
>variable : Symbol(variable, Decl(index.js, 19, 13))
this.property = `foo`; // Correctly inferred as `string`
>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 : 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`
>localProperty : Symbol(localProperty, Decl(index.js, 24, 13))
>variable : Symbol(variable, Decl(index.js, 19, 13))
}
}

Просмотреть файл

@ -55,3 +55,59 @@ class MyClass {
> : ^^^^^^^^^^^
}
}
class MyClass2 {
>MyClass2 : MyClass2
> : ^^^^^^^^
accessor property;
>property : string
> : ^^^^^^
accessor property2;
>property2 : string
> : ^^^^^^
constructor() {
const variable = 'something'
>variable : "something"
> : ^^^^^^^^^^^
>'something' : "something"
> : ^^^^^^^^^^^
this.property = `foo`; // Correctly inferred as `string`
>this.property = `foo` : "foo"
> : ^^^^^
>this.property : string
> : ^^^^^^
>this : this
> : ^^^^
>property : string
> : ^^^^^^
>`foo` : "foo"
> : ^^^^^
this.property2 = `foo-${variable}`; // Causes an error
>this.property2 = `foo-${variable}` : "foo-something"
> : ^^^^^^^^^^^^^^^
>this.property2 : string
> : ^^^^^^
>this : this
> : ^^^^
>property2 : string
> : ^^^^^^
>`foo-${variable}` : "foo-something"
> : ^^^^^^^^^^^^^^^
>variable : "something"
> : ^^^^^^^^^^^
const localProperty = `foo-${variable}`; // Correctly inferred as `string`
>localProperty : "foo-something"
> : ^^^^^^^^^^^^^^^
>`foo-${variable}` : "foo-something"
> : ^^^^^^^^^^^^^^^
>variable : "something"
> : ^^^^^^^^^^^
}
}

Просмотреть файл

@ -0,0 +1,37 @@
//// [tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef4.ts] ////
//// [classStaticBlockUseBeforeDef4.ts]
class C {
static accessor x;
static {
this.x = 1;
}
static accessor y = this.x;
static accessor z;
static {
this.z = this.y;
}
}
//// [classStaticBlockUseBeforeDef4.js]
"use strict";
class C {
static accessor x;
static {
this.x = 1;
}
static accessor y = this.x;
static accessor z;
static {
this.z = this.y;
}
}
//// [classStaticBlockUseBeforeDef4.d.ts]
declare class C {
static accessor x: number;
static accessor y: number;
static accessor z: number;
}

Просмотреть файл

@ -0,0 +1,35 @@
//// [tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef4.ts] ////
=== classStaticBlockUseBeforeDef4.ts ===
class C {
>C : Symbol(C, Decl(classStaticBlockUseBeforeDef4.ts, 0, 0))
static accessor x;
>x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef4.ts, 0, 9))
static {
this.x = 1;
>this.x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef4.ts, 0, 9))
>this : Symbol(C, Decl(classStaticBlockUseBeforeDef4.ts, 0, 0))
>x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef4.ts, 0, 9))
}
static accessor y = this.x;
>y : Symbol(C.y, Decl(classStaticBlockUseBeforeDef4.ts, 4, 5))
>this.x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef4.ts, 0, 9))
>this : Symbol(C, Decl(classStaticBlockUseBeforeDef4.ts, 0, 0))
>x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef4.ts, 0, 9))
static accessor z;
>z : Symbol(C.z, Decl(classStaticBlockUseBeforeDef4.ts, 5, 31))
static {
this.z = this.y;
>this.z : Symbol(C.z, Decl(classStaticBlockUseBeforeDef4.ts, 5, 31))
>this : Symbol(C, Decl(classStaticBlockUseBeforeDef4.ts, 0, 0))
>z : Symbol(C.z, Decl(classStaticBlockUseBeforeDef4.ts, 5, 31))
>this.y : Symbol(C.y, Decl(classStaticBlockUseBeforeDef4.ts, 4, 5))
>this : Symbol(C, Decl(classStaticBlockUseBeforeDef4.ts, 0, 0))
>y : Symbol(C.y, Decl(classStaticBlockUseBeforeDef4.ts, 4, 5))
}
}

Просмотреть файл

@ -0,0 +1,57 @@
//// [tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef4.ts] ////
=== classStaticBlockUseBeforeDef4.ts ===
class C {
>C : C
> : ^
static accessor x;
>x : number
> : ^^^^^^
static {
this.x = 1;
>this.x = 1 : 1
> : ^
>this.x : number
> : ^^^^^^
>this : typeof C
> : ^^^^^^^^
>x : number
> : ^^^^^^
>1 : 1
> : ^
}
static accessor y = this.x;
>y : number
> : ^^^^^^
>this.x : number
> : ^^^^^^
>this : typeof C
> : ^^^^^^^^
>x : number
> : ^^^^^^
static accessor z;
>z : number
> : ^^^^^^
static {
this.z = this.y;
>this.z = this.y : number
> : ^^^^^^
>this.z : number
> : ^^^^^^
>this : typeof C
> : ^^^^^^^^
>z : number
> : ^^^^^^
>this.y : number
> : ^^^^^^
>this : typeof C
> : ^^^^^^^^
>y : number
> : ^^^^^^
}
}

Просмотреть файл

@ -0,0 +1,14 @@
classStaticBlockUseBeforeDef5.ts(3,14): error TS2729: Property 'x' is used before its initialization.
==== classStaticBlockUseBeforeDef5.ts (1 errors) ====
class C {
static {
this.x = 1;
~
!!! error TS2729: Property 'x' is used before its initialization.
!!! related TS2728 classStaticBlockUseBeforeDef5.ts:5:21: 'x' is declared here.
}
static accessor x;
}

Просмотреть файл

@ -0,0 +1,25 @@
//// [tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef5.ts] ////
//// [classStaticBlockUseBeforeDef5.ts]
class C {
static {
this.x = 1;
}
static accessor x;
}
//// [classStaticBlockUseBeforeDef5.js]
"use strict";
class C {
static {
this.x = 1;
}
static accessor x;
}
//// [classStaticBlockUseBeforeDef5.d.ts]
declare class C {
static accessor x: number;
}

Просмотреть файл

@ -0,0 +1,16 @@
//// [tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef5.ts] ////
=== classStaticBlockUseBeforeDef5.ts ===
class C {
>C : Symbol(C, Decl(classStaticBlockUseBeforeDef5.ts, 0, 0))
static {
this.x = 1;
>this.x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef5.ts, 3, 5))
>this : Symbol(C, Decl(classStaticBlockUseBeforeDef5.ts, 0, 0))
>x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef5.ts, 3, 5))
}
static accessor x;
>x : Symbol(C.x, Decl(classStaticBlockUseBeforeDef5.ts, 3, 5))
}

Просмотреть файл

@ -0,0 +1,25 @@
//// [tests/cases/conformance/classes/classStaticBlock/classStaticBlockUseBeforeDef5.ts] ////
=== classStaticBlockUseBeforeDef5.ts ===
class C {
>C : C
> : ^
static {
this.x = 1;
>this.x = 1 : 1
> : ^
>this.x : number
> : ^^^^^^
>this : typeof C
> : ^^^^^^^^
>x : number
> : ^^^^^^
>1 : 1
> : ^
}
static accessor x;
>x : number
> : ^^^^^^
}

Просмотреть файл

@ -0,0 +1,64 @@
controlFlowAutoAccessor1.ts(54,19): error TS7008: Member 'value' implicitly has an 'any' type.
==== controlFlowAutoAccessor1.ts (1 errors) ====
class Example {
accessor test;
constructor(test: number) {
this.test = test;
}
getTest() {
return this.test;
}
}
class Example2 {
accessor test;
constructor(test: number | undefined) {
this.test = test;
}
getTest() {
if (this.test) {
return this.test;
}
return 0;
}
}
// https://github.com/microsoft/TypeScript/issues/59728
class Example3 {
accessor value;
constructor(n: number) {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
declare var n: number;
class Example4 {
static accessor value;
static {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
class Example5 {
static accessor value; // error
~~~~~
!!! error TS7008: Member 'value' implicitly has an 'any' type.
}
Example5.value = 123;
Example5.value++;

Просмотреть файл

@ -0,0 +1,133 @@
//// [tests/cases/compiler/controlFlowAutoAccessor1.ts] ////
//// [controlFlowAutoAccessor1.ts]
class Example {
accessor test;
constructor(test: number) {
this.test = test;
}
getTest() {
return this.test;
}
}
class Example2 {
accessor test;
constructor(test: number | undefined) {
this.test = test;
}
getTest() {
if (this.test) {
return this.test;
}
return 0;
}
}
// https://github.com/microsoft/TypeScript/issues/59728
class Example3 {
accessor value;
constructor(n: number) {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
declare var n: number;
class Example4 {
static accessor value;
static {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
class Example5 {
static accessor value; // error
}
Example5.value = 123;
Example5.value++;
//// [controlFlowAutoAccessor1.js]
"use strict";
class Example {
accessor test;
constructor(test) {
this.test = test;
}
getTest() {
return this.test;
}
}
class Example2 {
accessor test;
constructor(test) {
this.test = test;
}
getTest() {
if (this.test) {
return this.test;
}
return 0;
}
}
// https://github.com/microsoft/TypeScript/issues/59728
class Example3 {
accessor value;
constructor(n) {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
class Example4 {
static accessor value;
static {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
class Example5 {
static accessor value; // error
}
Example5.value = 123;
Example5.value++;
//// [controlFlowAutoAccessor1.d.ts]
declare class Example {
accessor test: number;
constructor(test: number);
getTest(): number;
}
declare class Example2 {
accessor test: number | undefined;
constructor(test: number | undefined);
getTest(): number;
}
declare class Example3 {
accessor value: number | null;
constructor(n: number);
}
declare var n: number;
declare class Example4 {
static accessor value: number | null;
}
declare class Example5 {
static accessor value: any;
}

Просмотреть файл

@ -0,0 +1,133 @@
//// [tests/cases/compiler/controlFlowAutoAccessor1.ts] ////
=== controlFlowAutoAccessor1.ts ===
class Example {
>Example : Symbol(Example, Decl(controlFlowAutoAccessor1.ts, 0, 0))
accessor test;
>test : Symbol(Example.test, Decl(controlFlowAutoAccessor1.ts, 0, 15))
constructor(test: number) {
>test : Symbol(test, Decl(controlFlowAutoAccessor1.ts, 3, 14))
this.test = test;
>this.test : Symbol(Example.test, Decl(controlFlowAutoAccessor1.ts, 0, 15))
>this : Symbol(Example, Decl(controlFlowAutoAccessor1.ts, 0, 0))
>test : Symbol(Example.test, Decl(controlFlowAutoAccessor1.ts, 0, 15))
>test : Symbol(test, Decl(controlFlowAutoAccessor1.ts, 3, 14))
}
getTest() {
>getTest : Symbol(Example.getTest, Decl(controlFlowAutoAccessor1.ts, 5, 3))
return this.test;
>this.test : Symbol(Example.test, Decl(controlFlowAutoAccessor1.ts, 0, 15))
>this : Symbol(Example, Decl(controlFlowAutoAccessor1.ts, 0, 0))
>test : Symbol(Example.test, Decl(controlFlowAutoAccessor1.ts, 0, 15))
}
}
class Example2 {
>Example2 : Symbol(Example2, Decl(controlFlowAutoAccessor1.ts, 10, 1))
accessor test;
>test : Symbol(Example2.test, Decl(controlFlowAutoAccessor1.ts, 12, 16))
constructor(test: number | undefined) {
>test : Symbol(test, Decl(controlFlowAutoAccessor1.ts, 15, 14))
this.test = test;
>this.test : Symbol(Example2.test, Decl(controlFlowAutoAccessor1.ts, 12, 16))
>this : Symbol(Example2, Decl(controlFlowAutoAccessor1.ts, 10, 1))
>test : Symbol(Example2.test, Decl(controlFlowAutoAccessor1.ts, 12, 16))
>test : Symbol(test, Decl(controlFlowAutoAccessor1.ts, 15, 14))
}
getTest() {
>getTest : Symbol(Example2.getTest, Decl(controlFlowAutoAccessor1.ts, 17, 3))
if (this.test) {
>this.test : Symbol(Example2.test, Decl(controlFlowAutoAccessor1.ts, 12, 16))
>this : Symbol(Example2, Decl(controlFlowAutoAccessor1.ts, 10, 1))
>test : Symbol(Example2.test, Decl(controlFlowAutoAccessor1.ts, 12, 16))
return this.test;
>this.test : Symbol(Example2.test, Decl(controlFlowAutoAccessor1.ts, 12, 16))
>this : Symbol(Example2, Decl(controlFlowAutoAccessor1.ts, 10, 1))
>test : Symbol(Example2.test, Decl(controlFlowAutoAccessor1.ts, 12, 16))
}
return 0;
}
}
// https://github.com/microsoft/TypeScript/issues/59728
class Example3 {
>Example3 : Symbol(Example3, Decl(controlFlowAutoAccessor1.ts, 25, 1))
accessor value;
>value : Symbol(Example3.value, Decl(controlFlowAutoAccessor1.ts, 29, 16))
constructor(n: number) {
>n : Symbol(n, Decl(controlFlowAutoAccessor1.ts, 32, 14))
this.value = n;
>this.value : Symbol(Example3.value, Decl(controlFlowAutoAccessor1.ts, 29, 16))
>this : Symbol(Example3, Decl(controlFlowAutoAccessor1.ts, 25, 1))
>value : Symbol(Example3.value, Decl(controlFlowAutoAccessor1.ts, 29, 16))
>n : Symbol(n, Decl(controlFlowAutoAccessor1.ts, 32, 14))
if (n < 0) {
>n : Symbol(n, Decl(controlFlowAutoAccessor1.ts, 32, 14))
this.value = null;
>this.value : Symbol(Example3.value, Decl(controlFlowAutoAccessor1.ts, 29, 16))
>this : Symbol(Example3, Decl(controlFlowAutoAccessor1.ts, 25, 1))
>value : Symbol(Example3.value, Decl(controlFlowAutoAccessor1.ts, 29, 16))
}
}
}
declare var n: number;
>n : Symbol(n, Decl(controlFlowAutoAccessor1.ts, 41, 11))
class Example4 {
>Example4 : Symbol(Example4, Decl(controlFlowAutoAccessor1.ts, 41, 22))
static accessor value;
>value : Symbol(Example4.value, Decl(controlFlowAutoAccessor1.ts, 42, 16))
static {
this.value = n;
>this.value : Symbol(Example4.value, Decl(controlFlowAutoAccessor1.ts, 42, 16))
>this : Symbol(Example4, Decl(controlFlowAutoAccessor1.ts, 41, 22))
>value : Symbol(Example4.value, Decl(controlFlowAutoAccessor1.ts, 42, 16))
>n : Symbol(n, Decl(controlFlowAutoAccessor1.ts, 41, 11))
if (n < 0) {
>n : Symbol(n, Decl(controlFlowAutoAccessor1.ts, 41, 11))
this.value = null;
>this.value : Symbol(Example4.value, Decl(controlFlowAutoAccessor1.ts, 42, 16))
>this : Symbol(Example4, Decl(controlFlowAutoAccessor1.ts, 41, 22))
>value : Symbol(Example4.value, Decl(controlFlowAutoAccessor1.ts, 42, 16))
}
}
}
class Example5 {
>Example5 : Symbol(Example5, Decl(controlFlowAutoAccessor1.ts, 50, 1))
static accessor value; // error
>value : Symbol(Example5.value, Decl(controlFlowAutoAccessor1.ts, 52, 16))
}
Example5.value = 123;
>Example5.value : Symbol(Example5.value, Decl(controlFlowAutoAccessor1.ts, 52, 16))
>Example5 : Symbol(Example5, Decl(controlFlowAutoAccessor1.ts, 50, 1))
>value : Symbol(Example5.value, Decl(controlFlowAutoAccessor1.ts, 52, 16))
Example5.value++;
>Example5.value : Symbol(Example5.value, Decl(controlFlowAutoAccessor1.ts, 52, 16))
>Example5 : Symbol(Example5, Decl(controlFlowAutoAccessor1.ts, 50, 1))
>value : Symbol(Example5.value, Decl(controlFlowAutoAccessor1.ts, 52, 16))

Просмотреть файл

@ -0,0 +1,216 @@
//// [tests/cases/compiler/controlFlowAutoAccessor1.ts] ////
=== controlFlowAutoAccessor1.ts ===
class Example {
>Example : Example
> : ^^^^^^^
accessor test;
>test : number
> : ^^^^^^
constructor(test: number) {
>test : number
> : ^^^^^^
this.test = test;
>this.test = test : number
> : ^^^^^^
>this.test : number
> : ^^^^^^
>this : this
> : ^^^^
>test : number
> : ^^^^^^
>test : number
> : ^^^^^^
}
getTest() {
>getTest : () => number
> : ^^^^^^^^^^^^
return this.test;
>this.test : number
> : ^^^^^^
>this : this
> : ^^^^
>test : number
> : ^^^^^^
}
}
class Example2 {
>Example2 : Example2
> : ^^^^^^^^
accessor test;
>test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
constructor(test: number | undefined) {
>test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
this.test = test;
>this.test = test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
>this.test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
>this : this
> : ^^^^
>test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
>test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
}
getTest() {
>getTest : () => number
> : ^^^^^^^^^^^^
if (this.test) {
>this.test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
>this : this
> : ^^^^
>test : number | undefined
> : ^^^^^^^^^^^^^^^^^^
return this.test;
>this.test : number
> : ^^^^^^
>this : this
> : ^^^^
>test : number
> : ^^^^^^
}
return 0;
>0 : 0
> : ^
}
}
// https://github.com/microsoft/TypeScript/issues/59728
class Example3 {
>Example3 : Example3
> : ^^^^^^^^
accessor value;
>value : number | null
> : ^^^^^^^^^^^^^
constructor(n: number) {
>n : number
> : ^^^^^^
this.value = n;
>this.value = n : number
> : ^^^^^^
>this.value : number | null
> : ^^^^^^^^^^^^^
>this : this
> : ^^^^
>value : number | null
> : ^^^^^^^^^^^^^
>n : number
> : ^^^^^^
if (n < 0) {
>n < 0 : boolean
> : ^^^^^^^
>n : number
> : ^^^^^^
>0 : 0
> : ^
this.value = null;
>this.value = null : null
> : ^^^^
>this.value : number | null
> : ^^^^^^^^^^^^^
>this : this
> : ^^^^
>value : number | null
> : ^^^^^^^^^^^^^
}
}
}
declare var n: number;
>n : number
> : ^^^^^^
class Example4 {
>Example4 : Example4
> : ^^^^^^^^
static accessor value;
>value : number | null
> : ^^^^^^^^^^^^^
static {
this.value = n;
>this.value = n : number
> : ^^^^^^
>this.value : number | null
> : ^^^^^^^^^^^^^
>this : typeof Example4
> : ^^^^^^^^^^^^^^^
>value : number | null
> : ^^^^^^^^^^^^^
>n : number
> : ^^^^^^
if (n < 0) {
>n < 0 : boolean
> : ^^^^^^^
>n : number
> : ^^^^^^
>0 : 0
> : ^
this.value = null;
>this.value = null : null
> : ^^^^
>this.value : number | null
> : ^^^^^^^^^^^^^
>this : typeof Example4
> : ^^^^^^^^^^^^^^^
>value : number | null
> : ^^^^^^^^^^^^^
}
}
}
class Example5 {
>Example5 : Example5
> : ^^^^^^^^
static accessor value; // error
>value : any
> : ^^^
}
Example5.value = 123;
>Example5.value = 123 : 123
> : ^^^
>Example5.value : any
> : ^^^
>Example5 : typeof Example5
> : ^^^^^^^^^^^^^^^
>value : any
> : ^^^
>123 : 123
> : ^^^
Example5.value++;
>Example5.value++ : number
> : ^^^^^^
>Example5.value : any
> : ^^^
>Example5 : typeof Example5
> : ^^^^^^^^^^^^^^^
>value : any
> : ^^^

Просмотреть файл

@ -0,0 +1,18 @@
// === Inlay Hints ===
accessor a = 1
^
{
"text": ": number",
"position": 24,
"kind": "Type",
"whitespaceBefore": true
}
accessor d;
^
{
"text": ": number | null",
"position": 86,
"kind": "Type",
"whitespaceBefore": true
}

Просмотреть файл

@ -0,0 +1,19 @@
// @strict: true
// @target: esnext
// @declaration: true
export class Cls {
accessor x;
accessor y;
accessor z;
accessor 0;
constructor(seed: number) {
this['x'] = [seed];
this['y'] = { seed };
this['z'] = `${seed}`;
this[0] = [seed];
}
}

Просмотреть файл

@ -1,4 +1,5 @@
// @strict: true
// @target: esnext
class MyClass {
property;
property2;
@ -11,4 +12,18 @@ class MyClass {
const localProperty = `foo-${variable}`; // Correctly inferred as `string`
}
}
}
class MyClass2 {
accessor property;
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`
}
}

Просмотреть файл

@ -1,4 +1,5 @@
// @noEmit: true
// @target: esnext
// @checkJs: true
// @strict: true
// @filename: index.js
@ -14,4 +15,18 @@ class MyClass {
const localProperty = `foo-${variable}`; // Correctly inferred as `string`
}
}
}
class MyClass2 {
accessor property;
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`
}
}

Просмотреть файл

@ -0,0 +1,61 @@
// @strict: true
// @target: esnext
// @declaration: true
class Example {
accessor test;
constructor(test: number) {
this.test = test;
}
getTest() {
return this.test;
}
}
class Example2 {
accessor test;
constructor(test: number | undefined) {
this.test = test;
}
getTest() {
if (this.test) {
return this.test;
}
return 0;
}
}
// https://github.com/microsoft/TypeScript/issues/59728
class Example3 {
accessor value;
constructor(n: number) {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
declare var n: number;
class Example4 {
static accessor value;
static {
this.value = n;
if (n < 0) {
this.value = null;
}
}
}
class Example5 {
static accessor value; // error
}
Example5.value = 123;
Example5.value++;

Просмотреть файл

@ -0,0 +1,15 @@
// @strict: true
// @target: esnext
// @declaration: true
class C {
static accessor x;
static {
this.x = 1;
}
static accessor y = this.x;
static accessor z;
static {
this.z = this.y;
}
}

Просмотреть файл

@ -0,0 +1,10 @@
// @strict: true
// @target: esnext
// @declaration: true
class C {
static {
this.x = 1;
}
static accessor x;
}

Просмотреть файл

@ -0,0 +1,21 @@
/// <reference path="fourslash.ts" />
// @strict: true
// @target: esnext
//// class C {
//// accessor a = 1
//// accessor b: number = 2
//// accessor c;
//// accessor d;
////
//// constructor(value: number) {
//// this.d = value;
//// if (value <= 0) {
//// this.d = null;
//// }
//// }
//// }
verify.baselineInlayHints(undefined, {
includeInlayPropertyDeclarationTypeHints: true,
});