@@ -7648,7 +7648,7 @@ namespace ts {
76487648 getInitialTypeOfBindingElement(<BindingElement>node);
76497649 }
76507650
7651- function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean) {
7651+ function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean ) {
76527652 let key: string;
76537653 if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
76547654 return declaredType;
@@ -7694,15 +7694,30 @@ namespace ts {
76947694 getTypeAtFlowBranchLabel(<FlowLabel>flow) :
76957695 getTypeAtFlowLoopLabel(<FlowLabel>flow);
76967696 }
7697- else if (flow.flags & FlowFlags.Unreachable) {
7697+ else if (flow.flags & FlowFlags.Start) {
7698+ let container = (<FlowStart>flow).container;
7699+ if (container) {
7700+ // If container is an IIFE continue with the control flow associated with the
7701+ // call expression node.
7702+ let iife = getImmediatelyInvokedFunctionExpression(<FunctionExpression>container);
7703+ if (iife && iife.flowNode) {
7704+ flow = iife.flowNode;
7705+ continue;
7706+ }
7707+ // Check if we should continue with the control flow of the containing function.
7708+ if (includeOuterFunctions && container.flowNode) {
7709+ flow = container.flowNode;
7710+ continue;
7711+ }
7712+ }
7713+ // At the top of the flow we have the initial type.
7714+ type = initialType;
7715+ }
7716+ else {
76987717 // Unreachable code errors are reported in the binding phase. Here we
76997718 // simply return the declared type to reduce follow-on errors.
77007719 type = declaredType;
77017720 }
7702- else {
7703- // At the top of the flow we have the initial type.
7704- type = initialType;
7705- }
77067721 if (flow.flags & FlowFlags.Shared) {
77077722 // Record visited node and the associated type in the cache.
77087723 visitedFlowNodes[visitedFlowCount] = flow;
@@ -8071,6 +8086,27 @@ namespace ts {
80718086 return expression;
80728087 }
80738088
8089+ function getControlFlowContainer(node: Identifier, declarationContainer: Node, skipFunctionExpressions: boolean) {
8090+ let container = getContainingFunctionOrModule(node);
8091+ while (container !== declarationContainer &&
8092+ (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.ArrowFunction) &&
8093+ (skipFunctionExpressions || getImmediatelyInvokedFunctionExpression(<FunctionExpression>container))) {
8094+ container = getContainingFunctionOrModule(container);
8095+ }
8096+ return container;
8097+ }
8098+
8099+ function isDeclarationIncludedInFlow(reference: Node, declaration: Declaration, includeOuterFunctions: boolean) {
8100+ const declarationContainer = getContainingFunctionOrModule(declaration);
8101+ let container = getContainingFunctionOrModule(reference);
8102+ while (container !== declarationContainer &&
8103+ (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.ArrowFunction) &&
8104+ (includeOuterFunctions || getImmediatelyInvokedFunctionExpression(<FunctionExpression>container))) {
8105+ container = getContainingFunctionOrModule(container);
8106+ }
8107+ return container === declarationContainer;
8108+ }
8109+
80748110 function checkIdentifier(node: Identifier): Type {
80758111 const symbol = getResolvedSymbol(node);
80768112
@@ -8127,10 +8163,11 @@ namespace ts {
81278163 return type;
81288164 }
81298165 const declaration = localOrExportSymbol.valueDeclaration;
8166+ const includeOuterFunctions = isReadonlySymbol(localOrExportSymbol);
81308167 const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || !declaration ||
81318168 getRootDeclaration(declaration).kind === SyntaxKind.Parameter || isInAmbientContext(declaration) ||
8132- getContainingFunctionOrModule(declaration) !== getContainingFunctionOrModule (node);
8133- const flowType = getFlowTypeOfReference(node, type, assumeInitialized);
8169+ !isDeclarationIncludedInFlow (node, declaration, includeOuterFunctions );
8170+ const flowType = getFlowTypeOfReference(node, type, assumeInitialized, includeOuterFunctions );
81348171 if (!assumeInitialized && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) {
81358172 error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
81368173 // Return the declared type to reduce follow-on errors
@@ -8379,7 +8416,7 @@ namespace ts {
83798416 if (isClassLike(container.parent)) {
83808417 const symbol = getSymbolOfNode(container.parent);
83818418 const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
8382- return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true);
8419+ return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true, /*includeOuterFunctions*/ true );
83838420 }
83848421
83858422 if (isInJavaScriptFile(node)) {
@@ -9991,7 +10028,7 @@ namespace ts {
999110028 return propType;
999210029 }
999310030 }
9994- return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true);
10031+ return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*includeOuterFunctions*/ false );
999510032 }
999610033
999710034 function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
0 commit comments