@@ -216,7 +216,7 @@ namespace ts {
216216 const flowLoopKeys: string[] = [];
217217 const flowLoopTypes: Type[][] = [];
218218 const visitedFlowNodes: FlowNode[] = [];
219- const visitedFlowTypes: Type [] = [];
219+ const visitedFlowTypes: FlowType [] = [];
220220 const potentialThisCollisions: Node[] = [];
221221 const awaitedTypeStack: number[] = [];
222222
@@ -1136,6 +1136,10 @@ namespace ts {
11361136 else {
11371137 symbolFromVariable = getPropertyOfVariable(targetSymbol, name.text);
11381138 }
1139+ // If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default
1140+ if (!symbolFromVariable && allowSyntheticDefaultImports && name.text === "default") {
1141+ symbolFromVariable = resolveExternalModuleSymbol(moduleSymbol) || resolveSymbol(moduleSymbol);
1142+ }
11391143 // if symbolFromVariable is export - get its final target
11401144 symbolFromVariable = resolveSymbol(symbolFromVariable);
11411145 const symbolFromModule = getExportOfModule(targetSymbol, name.text);
@@ -8094,21 +8098,33 @@ namespace ts {
80948098 f(type) ? type : neverType;
80958099 }
80968100
8101+ function isIncomplete(flowType: FlowType) {
8102+ return flowType.flags === 0;
8103+ }
8104+
8105+ function getTypeFromFlowType(flowType: FlowType) {
8106+ return flowType.flags === 0 ? (<IncompleteType>flowType).type : <Type>flowType;
8107+ }
8108+
8109+ function createFlowType(type: Type, incomplete: boolean): FlowType {
8110+ return incomplete ? { flags: 0, type } : type;
8111+ }
8112+
80978113 function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
80988114 let key: string;
80998115 if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
81008116 return declaredType;
81018117 }
81028118 const initialType = assumeInitialized ? declaredType : includeFalsyTypes(declaredType, TypeFlags.Undefined);
81038119 const visitedFlowStart = visitedFlowCount;
8104- const result = getTypeAtFlowNode(reference.flowNode);
8120+ const result = getTypeFromFlowType( getTypeAtFlowNode(reference.flowNode) );
81058121 visitedFlowCount = visitedFlowStart;
81068122 if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType) {
81078123 return declaredType;
81088124 }
81098125 return result;
81108126
8111- function getTypeAtFlowNode(flow: FlowNode): Type {
8127+ function getTypeAtFlowNode(flow: FlowNode): FlowType {
81128128 while (true) {
81138129 if (flow.flags & FlowFlags.Shared) {
81148130 // We cache results of flow type resolution for shared nodes that were previously visited in
@@ -8120,7 +8136,7 @@ namespace ts {
81208136 }
81218137 }
81228138 }
8123- let type: Type ;
8139+ let type: FlowType ;
81248140 if (flow.flags & FlowFlags.Assignment) {
81258141 type = getTypeAtFlowAssignment(<FlowAssignment>flow);
81268142 if (!type) {
@@ -8188,41 +8204,44 @@ namespace ts {
81888204 return undefined;
81898205 }
81908206
8191- function getTypeAtFlowCondition(flow: FlowCondition) {
8192- let type = getTypeAtFlowNode(flow.antecedent);
8207+ function getTypeAtFlowCondition(flow: FlowCondition): FlowType {
8208+ const flowType = getTypeAtFlowNode(flow.antecedent);
8209+ let type = getTypeFromFlowType(flowType);
81938210 if (type !== neverType) {
81948211 // If we have an antecedent type (meaning we're reachable in some way), we first
8195- // attempt to narrow the antecedent type. If that produces the nothing type, then
8196- // we take the type guard as an indication that control could reach here in a
8197- // manner not understood by the control flow analyzer (e.g. a function argument
8198- // has an invalid type, or a nested function has possibly made an assignment to a
8199- // captured variable). We proceed by reverting to the declared type and then
8212+ // attempt to narrow the antecedent type. If that produces the never type, and if
8213+ // the antecedent type is incomplete (i.e. a transient type in a loop), then we
8214+ // take the type guard as an indication that control *could* reach here once we
8215+ // have the complete type. We proceed by reverting to the declared type and then
82008216 // narrow that.
82018217 const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
82028218 type = narrowType(type, flow.expression, assumeTrue);
8203- if (type === neverType) {
8219+ if (type === neverType && isIncomplete(flowType) ) {
82048220 type = narrowType(declaredType, flow.expression, assumeTrue);
82058221 }
82068222 }
8207- return type;
8223+ return createFlowType( type, isIncomplete(flowType)) ;
82088224 }
82098225
8210- function getTypeAtSwitchClause(flow: FlowSwitchClause) {
8211- const type = getTypeAtFlowNode(flow.antecedent);
8226+ function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType {
8227+ const flowType = getTypeAtFlowNode(flow.antecedent);
8228+ let type = getTypeFromFlowType(flowType);
82128229 const expr = flow.switchStatement.expression;
82138230 if (isMatchingReference(reference, expr)) {
8214- return narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
8231+ type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
82158232 }
8216- if (isMatchingPropertyAccess(expr)) {
8217- return narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
8233+ else if (isMatchingPropertyAccess(expr)) {
8234+ type = narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
82188235 }
8219- return type;
8236+ return createFlowType( type, isIncomplete(flowType)) ;
82208237 }
82218238
8222- function getTypeAtFlowBranchLabel(flow: FlowLabel) {
8239+ function getTypeAtFlowBranchLabel(flow: FlowLabel): FlowType {
82238240 const antecedentTypes: Type[] = [];
8241+ let seenIncomplete = false;
82248242 for (const antecedent of flow.antecedents) {
8225- const type = getTypeAtFlowNode(antecedent);
8243+ const flowType = getTypeAtFlowNode(antecedent);
8244+ const type = getTypeFromFlowType(flowType);
82268245 // If the type at a particular antecedent path is the declared type and the
82278246 // reference is known to always be assigned (i.e. when declared and initial types
82288247 // are the same), there is no reason to process more antecedents since the only
@@ -8233,11 +8252,14 @@ namespace ts {
82338252 if (!contains(antecedentTypes, type)) {
82348253 antecedentTypes.push(type);
82358254 }
8255+ if (isIncomplete(flowType)) {
8256+ seenIncomplete = true;
8257+ }
82368258 }
8237- return getUnionType(antecedentTypes);
8259+ return createFlowType( getUnionType(antecedentTypes), seenIncomplete );
82388260 }
82398261
8240- function getTypeAtFlowLoopLabel(flow: FlowLabel) {
8262+ function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType {
82418263 // If we have previously computed the control flow type for the reference at
82428264 // this flow loop junction, return the cached type.
82438265 const id = getFlowNodeId(flow);
@@ -8249,12 +8271,12 @@ namespace ts {
82498271 return cache[key];
82508272 }
82518273 // If this flow loop junction and reference are already being processed, return
8252- // the union of the types computed for each branch so far. We should never see
8253- // an empty array here because the first antecedent of a loop junction is always
8254- // the non-looping control flow path that leads to the top.
8274+ // the union of the types computed for each branch so far, marked as incomplete.
8275+ // We should never see an empty array here because the first antecedent of a loop
8276+ // junction is always the non-looping control flow path that leads to the top.
82558277 for (let i = flowLoopStart; i < flowLoopCount; i++) {
82568278 if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key) {
8257- return getUnionType(flowLoopTypes[i]);
8279+ return createFlowType( getUnionType(flowLoopTypes[i]), /*incomplete*/ true );
82588280 }
82598281 }
82608282 // Add the flow loop junction and reference to the in-process stack and analyze
@@ -8265,7 +8287,7 @@ namespace ts {
82658287 flowLoopTypes[flowLoopCount] = antecedentTypes;
82668288 for (const antecedent of flow.antecedents) {
82678289 flowLoopCount++;
8268- const type = getTypeAtFlowNode(antecedent);
8290+ const type = getTypeFromFlowType( getTypeAtFlowNode(antecedent) );
82698291 flowLoopCount--;
82708292 // If we see a value appear in the cache it is a sign that control flow analysis
82718293 // was restarted and completed by checkExpressionCached. We can simply pick up
@@ -10068,7 +10090,7 @@ namespace ts {
1006810090 for (const prop of props) {
1006910091 // Is there a corresponding property in the element attributes type? Skip checking of properties
1007010092 // that have already been assigned to, as these are not actually pushed into the resulting type
10071- if (!nameTable[ prop.name] ) {
10093+ if (!hasProperty( nameTable, prop.name) ) {
1007210094 const targetPropSym = getPropertyOfType(elementAttributesType, prop.name);
1007310095 if (targetPropSym) {
1007410096 const msg = chainDiagnosticMessages(undefined, Diagnostics.Property_0_of_JSX_spread_attribute_is_not_assignable_to_target_property, prop.name);
@@ -10414,7 +10436,7 @@ namespace ts {
1041410436 const targetProperties = getPropertiesOfType(targetAttributesType);
1041510437 for (let i = 0; i < targetProperties.length; i++) {
1041610438 if (!(targetProperties[i].flags & SymbolFlags.Optional) &&
10417- nameTable[ targetProperties[i].name] === undefined ) {
10439+ !hasProperty( nameTable, targetProperties[i].name) ) {
1041810440
1041910441 error(node, Diagnostics.Property_0_is_missing_in_type_1, targetProperties[i].name, typeToString(targetAttributesType));
1042010442 }
@@ -19845,7 +19867,7 @@ namespace ts {
1984519867 }
1984619868
1984719869 function checkGrammarTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
19848- // A declare modifier is required for any top level .d.ts declaration except export=, export default,
19870+ // A declare modifier is required for any top level .d.ts declaration except export=, export default, export as namespace
1984919871 // interfaces and imports categories:
1985019872 //
1985119873 // DeclarationElement:
@@ -19863,8 +19885,8 @@ namespace ts {
1986319885 node.kind === SyntaxKind.ImportEqualsDeclaration ||
1986419886 node.kind === SyntaxKind.ExportDeclaration ||
1986519887 node.kind === SyntaxKind.ExportAssignment ||
19888+ node.kind === SyntaxKind.NamespaceExportDeclaration ||
1986619889 getModifierFlags(node) & (ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default)) {
19867-
1986819890 return false;
1986919891 }
1987019892
0 commit comments