Skip to content

Commit 3919042

Browse files
authored
Control flow for constructor initialized properties (microsoft#37920)
* Use CFA to determine types of properties declared by this.xxx assignments * Accept new baselines * Also use CFA in constructor functions * Accept new baselines * Fix lint error * Only widen fresh literal types in CFA of assignment to auto-typed * Auto-typing for declared properties with no type annotation or initializer * Add optionality if declaration includes '?' modifier * Always use CFA for properties with no initializer in .js files * Small fix
1 parent a0ebd2c commit 3919042

File tree

63 files changed

+327
-248
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+327
-248
lines changed

src/compiler/binder.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ namespace ts {
649649
}
650650
// We create a return control flow graph for IIFEs and constructors. For constructors
651651
// we use the return control flow graph in strict property initialization checks.
652-
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
652+
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || (isInJSFile && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
653653
currentExceptionTarget = undefined;
654654
currentBreakTarget = undefined;
655655
currentContinueTarget = undefined;
@@ -670,8 +670,8 @@ namespace ts {
670670
if (currentReturnTarget) {
671671
addAntecedent(currentReturnTarget, currentFlow);
672672
currentFlow = finishFlowLabel(currentReturnTarget);
673-
if (node.kind === SyntaxKind.Constructor) {
674-
(<ConstructorDeclaration>node).returnFlowNode = currentFlow;
673+
if (node.kind === SyntaxKind.Constructor || (isInJSFile && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
674+
(<FunctionLikeDeclaration>node).returnFlowNode = currentFlow;
675675
}
676676
}
677677
if (!isIIFE) {

src/compiler/checker.ts

Lines changed: 129 additions & 56 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,7 @@ namespace ts {
11071107
exclamationToken?: ExclamationToken;
11081108
body?: Block | Expression;
11091109
/* @internal */ endFlowNode?: FlowNode;
1110+
/* @internal */ returnFlowNode?: FlowNode;
11101111
}
11111112

11121113
export type FunctionLikeDeclaration =
@@ -1152,7 +1153,6 @@ namespace ts {
11521153
kind: SyntaxKind.Constructor;
11531154
parent: ClassLikeDeclaration;
11541155
body?: FunctionBody;
1155-
/* @internal */ returnFlowNode?: FlowNode;
11561156
}
11571157

11581158
/** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */
@@ -4157,6 +4157,7 @@ namespace ts {
41574157
deferralParent?: Type; // Source union/intersection of a deferred type
41584158
cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target
41594159
typeOnlyDeclaration?: TypeOnlyCompatibleAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs
4160+
isConstructorDeclaredProperty?: boolean; // Property declared through 'this.x = ...' assignment in constructor
41604161
}
41614162

41624163
/* @internal */

tests/baselines/reference/checkExportsObjectAssignPrototypeProperty.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ function Person(name) {
105105

106106
this.name = name;
107107
>this.name = name : string
108-
>this.name : string
108+
>this.name : any
109109
>this : this
110-
>name : string
110+
>name : any
111111
>name : string
112112
}
113113
Person.prototype.describe = function () {

tests/baselines/reference/checkIndexConstraintOfJavascriptClassExpression.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ someFunction(function(BaseClass) {
2323

2424
this.foo = "bar";
2525
>this.foo = "bar" : "bar"
26-
>this.foo : string
26+
>this.foo : any
2727
>this : this
28-
>foo : string
28+
>foo : any
2929
>"bar" : "bar"
3030
}
3131
_render(error) {

tests/baselines/reference/checkJsFiles_noErrorLocation.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ class B extends A {
2525

2626
this.foo = () => 3;
2727
>this.foo = () => 3 : () => number
28-
>this.foo : () => number
28+
>this.foo : any
2929
>this : this
30-
>foo : () => number
30+
>foo : any
3131
>() => 3 : () => number
3232
>3 : 3
3333
}

tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ class Derived {
1212

1313
this.x = 10;
1414
>this.x = 10 : 10
15-
>this.x : number
15+
>this.x : any
1616
>this : this
17-
>x : number
17+
>x : any
1818
>10 : 10
1919

2020
var that = this;

tests/baselines/reference/classCanExtendConstructorFunction.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ function Wagon(numberOxen) {
99

1010
this.numberOxen = numberOxen
1111
>this.numberOxen = numberOxen : number
12-
>this.numberOxen : number
12+
>this.numberOxen : any
1313
>this : this
14-
>numberOxen : number
14+
>numberOxen : any
1515
>numberOxen : number
1616
}
1717
/** @param {Wagon[]=} wagons */
@@ -91,9 +91,9 @@ class Sql extends Wagon {
9191

9292
this.foonly = 12
9393
>this.foonly = 12 : 12
94-
>this.foonly : number
94+
>this.foonly : any
9595
>this : this
96-
>foonly : number
96+
>foonly : any
9797
>12 : 12
9898
}
9999
/**

tests/baselines/reference/classExtendingAny.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ class B extends Err {
6767

6868
this.wat = 12
6969
>this.wat = 12 : 12
70-
>this.wat : number
70+
>this.wat : any
7171
>this : this
72-
>wat : number
72+
>wat : any
7373
>12 : 12
7474
}
7575
f() {

tests/baselines/reference/constructorFunctions.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ function C6() {
143143

144144
this.functions = [x => x, x => x + 1, x => x - 1]
145145
>this.functions = [x => x, x => x + 1, x => x - 1] : ((x: any) => any)[]
146-
>this.functions : ((x: any) => any)[]
146+
>this.functions : any
147147
>this : this
148-
>functions : ((x: any) => any)[]
148+
>functions : any
149149
>[x => x, x => x + 1, x => x - 1] : ((x: any) => any)[]
150150
>x => x : (x: any) => any
151151
>x : any

0 commit comments

Comments
 (0)