Skip to content

Commit 5770157

Browse files
committed
Adding more comments
1 parent 15dae3f commit 5770157

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

src/compiler/checker.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8809,21 +8809,34 @@ namespace ts {
88098809

88108810
const type = getTypeOfSymbol(localOrExportSymbol);
88118811
const declaration = localOrExportSymbol.valueDeclaration;
8812+
// We only narrow variables and parameters occurring in a non-assignment position. For all other
8813+
// entities we simply return the declared type.
88128814
if (!(localOrExportSymbol.flags & SymbolFlags.Variable) || isAssignmentTarget(node) || !declaration) {
88138815
return type;
88148816
}
8815-
8817+
// The declaration container is the innermost function that encloses the declaration of the variable
8818+
// or parameter. The flow container is the innermost function starting with which we analyze the control
8819+
// flow graph to determine the control flow based type.
88168820
const isParameter = getRootDeclaration(declaration).kind === SyntaxKind.Parameter;
88178821
const declarationContainer = getControlFlowContainer(declaration);
88188822
let flowContainer = getControlFlowContainer(node);
8823+
// When the control flow originates in a function expression or arrow function and we are referencing
8824+
// a const variable or parameter from an outer function, we extend the origin of the control flow
8825+
// analysis to include the immediately enclosing function.
88198826
while (flowContainer !== declarationContainer &&
88208827
(flowContainer.kind === SyntaxKind.FunctionExpression || flowContainer.kind === SyntaxKind.ArrowFunction) &&
88218828
(isReadonlySymbol(localOrExportSymbol) || isParameter && !isParameterAssigned(localOrExportSymbol))) {
88228829
flowContainer = getControlFlowContainer(flowContainer);
88238830
}
8831+
// We only look for uninitialized variables in strict null checking mode, and only when we can analyze
8832+
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
8833+
// declaration container are the same).
88248834
const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isParameter ||
88258835
flowContainer !== declarationContainer || isInAmbientContext(declaration);
88268836
const flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer);
8837+
// A variable is considered uninitialized when it is possible to analyze the entire control flow graph
8838+
// from declaration to use, and when the variable's declared type doesn't include undefined but the
8839+
// control flow based type does include undefined.
88278840
if (!assumeInitialized && !(getFalsyFlags(type) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
88288841
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
88298842
// Return the declared type to reduce follow-on errors

src/compiler/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2157,7 +2157,7 @@ namespace ts {
21572157
/* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol
21582158
/* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums
21592159
/* @internal */ isReferenced?: boolean; // True if the symbol is referenced elsewhere
2160-
/* @internal */ isAssigned?: boolean; // True if the symbol has assignments
2160+
/* @internal */ isAssigned?: boolean; // True if the symbol is a parameter with assignments
21612161
}
21622162

21632163
/* @internal */

0 commit comments

Comments
 (0)