@@ -216,7 +216,7 @@ namespace ts {
216
216
const flowLoopKeys: string[] = [];
217
217
const flowLoopTypes: Type[][] = [];
218
218
const visitedFlowNodes: FlowNode[] = [];
219
- const visitedFlowTypes: Type [] = [];
219
+ const visitedFlowTypes: FlowType [] = [];
220
220
const potentialThisCollisions: Node[] = [];
221
221
const awaitedTypeStack: number[] = [];
222
222
@@ -1136,6 +1136,10 @@ namespace ts {
1136
1136
else {
1137
1137
symbolFromVariable = getPropertyOfVariable(targetSymbol, name.text);
1138
1138
}
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
+ }
1139
1143
// if symbolFromVariable is export - get its final target
1140
1144
symbolFromVariable = resolveSymbol(symbolFromVariable);
1141
1145
const symbolFromModule = getExportOfModule(targetSymbol, name.text);
@@ -8094,21 +8098,33 @@ namespace ts {
8094
8098
f(type) ? type : neverType;
8095
8099
}
8096
8100
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
+
8097
8113
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
8098
8114
let key: string;
8099
8115
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
8100
8116
return declaredType;
8101
8117
}
8102
8118
const initialType = assumeInitialized ? declaredType : includeFalsyTypes(declaredType, TypeFlags.Undefined);
8103
8119
const visitedFlowStart = visitedFlowCount;
8104
- const result = getTypeAtFlowNode(reference.flowNode);
8120
+ const result = getTypeFromFlowType( getTypeAtFlowNode(reference.flowNode) );
8105
8121
visitedFlowCount = visitedFlowStart;
8106
8122
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType) {
8107
8123
return declaredType;
8108
8124
}
8109
8125
return result;
8110
8126
8111
- function getTypeAtFlowNode(flow: FlowNode): Type {
8127
+ function getTypeAtFlowNode(flow: FlowNode): FlowType {
8112
8128
while (true) {
8113
8129
if (flow.flags & FlowFlags.Shared) {
8114
8130
// We cache results of flow type resolution for shared nodes that were previously visited in
@@ -8120,7 +8136,7 @@ namespace ts {
8120
8136
}
8121
8137
}
8122
8138
}
8123
- let type: Type ;
8139
+ let type: FlowType ;
8124
8140
if (flow.flags & FlowFlags.Assignment) {
8125
8141
type = getTypeAtFlowAssignment(<FlowAssignment>flow);
8126
8142
if (!type) {
@@ -8188,41 +8204,44 @@ namespace ts {
8188
8204
return undefined;
8189
8205
}
8190
8206
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);
8193
8210
if (type !== neverType) {
8194
8211
// 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
8200
8216
// narrow that.
8201
8217
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
8202
8218
type = narrowType(type, flow.expression, assumeTrue);
8203
- if (type === neverType) {
8219
+ if (type === neverType && isIncomplete(flowType) ) {
8204
8220
type = narrowType(declaredType, flow.expression, assumeTrue);
8205
8221
}
8206
8222
}
8207
- return type;
8223
+ return createFlowType( type, isIncomplete(flowType)) ;
8208
8224
}
8209
8225
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);
8212
8229
const expr = flow.switchStatement.expression;
8213
8230
if (isMatchingReference(reference, expr)) {
8214
- return narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
8231
+ type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
8215
8232
}
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));
8218
8235
}
8219
- return type;
8236
+ return createFlowType( type, isIncomplete(flowType)) ;
8220
8237
}
8221
8238
8222
- function getTypeAtFlowBranchLabel(flow: FlowLabel) {
8239
+ function getTypeAtFlowBranchLabel(flow: FlowLabel): FlowType {
8223
8240
const antecedentTypes: Type[] = [];
8241
+ let seenIncomplete = false;
8224
8242
for (const antecedent of flow.antecedents) {
8225
- const type = getTypeAtFlowNode(antecedent);
8243
+ const flowType = getTypeAtFlowNode(antecedent);
8244
+ const type = getTypeFromFlowType(flowType);
8226
8245
// If the type at a particular antecedent path is the declared type and the
8227
8246
// reference is known to always be assigned (i.e. when declared and initial types
8228
8247
// are the same), there is no reason to process more antecedents since the only
@@ -8233,11 +8252,14 @@ namespace ts {
8233
8252
if (!contains(antecedentTypes, type)) {
8234
8253
antecedentTypes.push(type);
8235
8254
}
8255
+ if (isIncomplete(flowType)) {
8256
+ seenIncomplete = true;
8257
+ }
8236
8258
}
8237
- return getUnionType(antecedentTypes);
8259
+ return createFlowType( getUnionType(antecedentTypes), seenIncomplete );
8238
8260
}
8239
8261
8240
- function getTypeAtFlowLoopLabel(flow: FlowLabel) {
8262
+ function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType {
8241
8263
// If we have previously computed the control flow type for the reference at
8242
8264
// this flow loop junction, return the cached type.
8243
8265
const id = getFlowNodeId(flow);
@@ -8249,12 +8271,12 @@ namespace ts {
8249
8271
return cache[key];
8250
8272
}
8251
8273
// 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.
8255
8277
for (let i = flowLoopStart; i < flowLoopCount; i++) {
8256
8278
if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key) {
8257
- return getUnionType(flowLoopTypes[i]);
8279
+ return createFlowType( getUnionType(flowLoopTypes[i]), /*incomplete*/ true );
8258
8280
}
8259
8281
}
8260
8282
// Add the flow loop junction and reference to the in-process stack and analyze
@@ -8265,7 +8287,7 @@ namespace ts {
8265
8287
flowLoopTypes[flowLoopCount] = antecedentTypes;
8266
8288
for (const antecedent of flow.antecedents) {
8267
8289
flowLoopCount++;
8268
- const type = getTypeAtFlowNode(antecedent);
8290
+ const type = getTypeFromFlowType( getTypeAtFlowNode(antecedent) );
8269
8291
flowLoopCount--;
8270
8292
// If we see a value appear in the cache it is a sign that control flow analysis
8271
8293
// was restarted and completed by checkExpressionCached. We can simply pick up
@@ -10068,7 +10090,7 @@ namespace ts {
10068
10090
for (const prop of props) {
10069
10091
// Is there a corresponding property in the element attributes type? Skip checking of properties
10070
10092
// 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) ) {
10072
10094
const targetPropSym = getPropertyOfType(elementAttributesType, prop.name);
10073
10095
if (targetPropSym) {
10074
10096
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 {
10414
10436
const targetProperties = getPropertiesOfType(targetAttributesType);
10415
10437
for (let i = 0; i < targetProperties.length; i++) {
10416
10438
if (!(targetProperties[i].flags & SymbolFlags.Optional) &&
10417
- nameTable[ targetProperties[i].name] === undefined ) {
10439
+ !hasProperty( nameTable, targetProperties[i].name) ) {
10418
10440
10419
10441
error(node, Diagnostics.Property_0_is_missing_in_type_1, targetProperties[i].name, typeToString(targetAttributesType));
10420
10442
}
@@ -19845,7 +19867,7 @@ namespace ts {
19845
19867
}
19846
19868
19847
19869
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
19849
19871
// interfaces and imports categories:
19850
19872
//
19851
19873
// DeclarationElement:
@@ -19863,8 +19885,8 @@ namespace ts {
19863
19885
node.kind === SyntaxKind.ImportEqualsDeclaration ||
19864
19886
node.kind === SyntaxKind.ExportDeclaration ||
19865
19887
node.kind === SyntaxKind.ExportAssignment ||
19888
+ node.kind === SyntaxKind.NamespaceExportDeclaration ||
19866
19889
getModifierFlags(node) & (ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default)) {
19867
-
19868
19890
return false;
19869
19891
}
19870
19892
0 commit comments