@@ -7660,7 +7660,7 @@ namespace ts {
76607660 getInitialTypeOfBindingElement(<BindingElement>node);
76617661 }
76627662
7663- function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean) {
7663+ function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean ) {
76647664 let key: string;
76657665 if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
76667666 return declaredType;
@@ -7706,15 +7706,21 @@ namespace ts {
77067706 getTypeAtFlowBranchLabel(<FlowLabel>flow) :
77077707 getTypeAtFlowLoopLabel(<FlowLabel>flow);
77087708 }
7709- else if (flow.flags & FlowFlags.Unreachable) {
7709+ else if (flow.flags & FlowFlags.Start) {
7710+ // Check if we should continue with the control flow of the containing function.
7711+ const container = (<FlowStart>flow).container;
7712+ if (container && includeOuterFunctions) {
7713+ flow = container.flowNode;
7714+ continue;
7715+ }
7716+ // At the top of the flow we have the initial type.
7717+ type = initialType;
7718+ }
7719+ else {
77107720 // Unreachable code errors are reported in the binding phase. Here we
77117721 // simply return the declared type to reduce follow-on errors.
77127722 type = declaredType;
77137723 }
7714- else {
7715- // At the top of the flow we have the initial type.
7716- type = initialType;
7717- }
77187724 if (flow.flags & FlowFlags.Shared) {
77197725 // Record visited node and the associated type in the cache.
77207726 visitedFlowNodes[visitedFlowCount] = flow;
@@ -8083,6 +8089,17 @@ namespace ts {
80838089 return expression;
80848090 }
80858091
8092+ function isDeclarationIncludedInFlow(reference: Node, declaration: Declaration, includeOuterFunctions: boolean) {
8093+ const declarationContainer = getContainingFunctionOrModule(declaration);
8094+ let container = getContainingFunctionOrModule(reference);
8095+ while (container !== declarationContainer &&
8096+ (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.ArrowFunction) &&
8097+ (includeOuterFunctions || getImmediatelyInvokedFunctionExpression(<FunctionExpression>container))) {
8098+ container = getContainingFunctionOrModule(container);
8099+ }
8100+ return container === declarationContainer;
8101+ }
8102+
80868103 function checkIdentifier(node: Identifier): Type {
80878104 const symbol = getResolvedSymbol(node);
80888105
@@ -8139,10 +8156,11 @@ namespace ts {
81398156 return type;
81408157 }
81418158 const declaration = localOrExportSymbol.valueDeclaration;
8159+ const includeOuterFunctions = isReadonlySymbol(localOrExportSymbol);
81428160 const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || !declaration ||
81438161 getRootDeclaration(declaration).kind === SyntaxKind.Parameter || isInAmbientContext(declaration) ||
8144- getContainingFunctionOrModule(declaration) !== getContainingFunctionOrModule (node);
8145- const flowType = getFlowTypeOfReference(node, type, assumeInitialized);
8162+ !isDeclarationIncludedInFlow (node, declaration, includeOuterFunctions );
8163+ const flowType = getFlowTypeOfReference(node, type, assumeInitialized, includeOuterFunctions );
81468164 if (!assumeInitialized && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) {
81478165 error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
81488166 // Return the declared type to reduce follow-on errors
@@ -8391,7 +8409,7 @@ namespace ts {
83918409 if (isClassLike(container.parent)) {
83928410 const symbol = getSymbolOfNode(container.parent);
83938411 const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
8394- return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true);
8412+ return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true, /*includeOuterFunctions*/ true );
83958413 }
83968414
83978415 if (isInJavaScriptFile(node)) {
@@ -8637,23 +8655,25 @@ namespace ts {
86378655 function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
86388656 const func = parameter.parent;
86398657 if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
8640- const iife = getImmediatelyInvokedFunctionExpression(func);
8641- if (iife) {
8642- const indexOfParameter = indexOf(func.parameters, parameter);
8643- if (iife.arguments && indexOfParameter < iife.arguments.length) {
8644- if (parameter.dotDotDotToken) {
8645- const restTypes: Type[] = [];
8646- for (let i = indexOfParameter; i < iife.arguments.length; i++) {
8647- restTypes.push(getTypeOfExpression(iife.arguments[i]));
8658+ if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) {
8659+ const iife = getImmediatelyInvokedFunctionExpression(func);
8660+ if (iife) {
8661+ const indexOfParameter = indexOf(func.parameters, parameter);
8662+ if (iife.arguments && indexOfParameter < iife.arguments.length) {
8663+ if (parameter.dotDotDotToken) {
8664+ const restTypes: Type[] = [];
8665+ for (let i = indexOfParameter; i < iife.arguments.length; i++) {
8666+ restTypes.push(getTypeOfExpression(iife.arguments[i]));
8667+ }
8668+ return createArrayType(getUnionType(restTypes));
86488669 }
8649- return createArrayType(getUnionType(restTypes));
8670+ const links = getNodeLinks(iife);
8671+ const cached = links.resolvedSignature;
8672+ links.resolvedSignature = anySignature;
8673+ const type = checkExpression(iife.arguments[indexOfParameter]);
8674+ links.resolvedSignature = cached;
8675+ return type;
86508676 }
8651- const links = getNodeLinks(iife);
8652- const cached = links.resolvedSignature;
8653- links.resolvedSignature = anySignature;
8654- const type = checkExpression(iife.arguments[indexOfParameter]);
8655- links.resolvedSignature = cached;
8656- return type;
86578677 }
86588678 }
86598679 const contextualSignature = getContextualSignature(func);
@@ -8676,20 +8696,6 @@ namespace ts {
86768696 return undefined;
86778697 }
86788698
8679- function getImmediatelyInvokedFunctionExpression(func: FunctionExpression | MethodDeclaration) {
8680- if (isFunctionExpressionOrArrowFunction(func)) {
8681- let prev: Node = func;
8682- let parent: Node = func.parent;
8683- while (parent.kind === SyntaxKind.ParenthesizedExpression) {
8684- prev = parent;
8685- parent = parent.parent;
8686- }
8687- if (parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === prev) {
8688- return parent as CallExpression;
8689- }
8690- }
8691- }
8692-
86938699 // In a variable, parameter or property declaration with a type annotation,
86948700 // the contextual type of an initializer expression is the type of the variable, parameter or property.
86958701 // Otherwise, in a parameter declaration of a contextually typed function expression,
@@ -10003,7 +10009,7 @@ namespace ts {
1000310009 return propType;
1000410010 }
1000510011 }
10006- return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true);
10012+ return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*includeOuterFunctions*/ false );
1000710013 }
1000810014
1000910015 function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
0 commit comments