@@ -472,9 +472,7 @@ namespace ts {
472
472
// other kinds of value declarations take precedence over modules
473
473
target.valueDeclaration = source.valueDeclaration;
474
474
}
475
- forEach(source.declarations, node => {
476
- target.declarations.push(node);
477
- });
475
+ addRange(target.declarations, source.declarations);
478
476
if (source.members) {
479
477
if (!target.members) target.members = createMap<Symbol>();
480
478
mergeSymbolTable(target.members, source.members);
@@ -1106,7 +1104,7 @@ namespace ts {
1106
1104
}
1107
1105
1108
1106
function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined {
1109
- return forEach (symbol.declarations, d => isAliasSymbolDeclaration(d) ? d : undefined );
1107
+ return find<Declaration> (symbol.declarations, isAliasSymbolDeclaration);
1110
1108
}
1111
1109
1112
1110
function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration): Symbol {
@@ -1447,9 +1445,8 @@ namespace ts {
1447
1445
// May be an untyped module. If so, ignore resolutionDiagnostic.
1448
1446
if (!isRelative && resolvedModule && !extensionIsTypeScript(resolvedModule.extension)) {
1449
1447
if (isForAugmentation) {
1450
- Debug.assert(!!moduleNotFoundError);
1451
1448
const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
1452
- error(errorNode, diag, moduleName , resolvedModule.resolvedFileName);
1449
+ error(errorNode, diag, moduleReference , resolvedModule.resolvedFileName);
1453
1450
}
1454
1451
else if (compilerOptions.noImplicitAny && moduleNotFoundError) {
1455
1452
error(errorNode,
@@ -1750,7 +1747,19 @@ namespace ts {
1750
1747
}
1751
1748
1752
1749
function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, useOnlyExternalAliasing: boolean): Symbol[] {
1753
- function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] {
1750
+ function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable) {
1751
+ return getAccessibleSymbolChainFromSymbolTableWorker(symbols, []);
1752
+ }
1753
+
1754
+ function getAccessibleSymbolChainFromSymbolTableWorker(symbols: SymbolTable, visitedSymbolTables: SymbolTable[]): Symbol[] {
1755
+ if (contains(visitedSymbolTables, symbols)) {
1756
+ return undefined;
1757
+ }
1758
+ visitedSymbolTables.push(symbols);
1759
+ const result = trySymbolTable(symbols);
1760
+ visitedSymbolTables.pop();
1761
+ return result;
1762
+
1754
1763
function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) {
1755
1764
// If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
1756
1765
if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
@@ -1772,34 +1781,36 @@ namespace ts {
1772
1781
}
1773
1782
}
1774
1783
1775
- // If symbol is directly available by its name in the symbol table
1776
- if (isAccessible(symbols[symbol.name])) {
1777
- return [symbol];
1778
- }
1784
+ function trySymbolTable(symbols: SymbolTable) {
1785
+ // If symbol is directly available by its name in the symbol table
1786
+ if (isAccessible(symbols[symbol.name])) {
1787
+ return [symbol];
1788
+ }
1779
1789
1780
- // Check if symbol is any of the alias
1781
- return forEachProperty(symbols, symbolFromSymbolTable => {
1782
- if (symbolFromSymbolTable.flags & SymbolFlags.Alias
1783
- && symbolFromSymbolTable.name !== "export="
1784
- && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
1785
- if (!useOnlyExternalAliasing || // We can use any type of alias to get the name
1786
- // Is this external alias, then use it to name
1787
- ts.forEach(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) {
1790
+ // Check if symbol is any of the alias
1791
+ return forEachProperty(symbols, symbolFromSymbolTable => {
1792
+ if (symbolFromSymbolTable.flags & SymbolFlags.Alias
1793
+ && symbolFromSymbolTable.name !== "export="
1794
+ && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
1795
+ if (!useOnlyExternalAliasing || // We can use any type of alias to get the name
1796
+ // Is this external alias, then use it to name
1797
+ ts.forEach(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) {
1788
1798
1789
- const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
1790
- if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
1791
- return [symbolFromSymbolTable];
1792
- }
1799
+ const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
1800
+ if (isAccessible(symbolFromSymbolTable, resolveAlias(symbolFromSymbolTable))) {
1801
+ return [symbolFromSymbolTable];
1802
+ }
1793
1803
1794
- // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
1795
- // but only if the symbolFromSymbolTable can be qualified
1796
- const accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTable(resolvedImportedSymbol.exports) : undefined;
1797
- if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
1798
- return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
1804
+ // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
1805
+ // but only if the symbolFromSymbolTable can be qualified
1806
+ const accessibleSymbolsFromExports = resolvedImportedSymbol.exports ? getAccessibleSymbolChainFromSymbolTableWorker(resolvedImportedSymbol.exports, visitedSymbolTables) : undefined;
1807
+ if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
1808
+ return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
1809
+ }
1799
1810
}
1800
1811
}
1801
- }
1802
- });
1812
+ });
1813
+ }
1803
1814
}
1804
1815
1805
1816
if (symbol) {
@@ -4603,12 +4614,22 @@ namespace ts {
4603
4614
4604
4615
function getModifiersTypeFromMappedType(type: MappedType) {
4605
4616
if (!type.modifiersType) {
4606
- // If the mapped type was declared as { [P in keyof T]: X } or as { [P in K]: X }, where
4607
- // K is constrained to 'K extends keyof T', then we will copy property modifiers from T.
4608
- const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4609
- const constraint = getConstraintTypeFromMappedType(declaredType);
4610
- const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4611
- type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4617
+ const constraintDeclaration = type.declaration.typeParameter.constraint;
4618
+ if (constraintDeclaration.kind === SyntaxKind.TypeOperator) {
4619
+ // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check
4620
+ // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves
4621
+ // 'keyof T' to a literal union type and we can't recover T from that type.
4622
+ type.modifiersType = instantiateType(getTypeFromTypeNode((<TypeOperatorNode>constraintDeclaration).type), type.mapper || identityMapper);
4623
+ }
4624
+ else {
4625
+ // Otherwise, get the declared constraint type, and if the constraint type is a type parameter,
4626
+ // get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T',
4627
+ // the modifiers type is T. Otherwise, the modifiers type is {}.
4628
+ const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4629
+ const constraint = getConstraintTypeFromMappedType(declaredType);
4630
+ const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4631
+ type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4632
+ }
4612
4633
}
4613
4634
return type.modifiersType;
4614
4635
}
@@ -7224,6 +7245,25 @@ namespace ts {
7224
7245
}
7225
7246
}
7226
7247
7248
+ function isUnionOrIntersectionTypeWithoutNullableConstituents(type: Type): boolean {
7249
+ if (!(type.flags & TypeFlags.UnionOrIntersection)) {
7250
+ return false;
7251
+ }
7252
+ // at this point we know that this is union or intersection type possibly with nullable constituents.
7253
+ // check if we still will have compound type if we ignore nullable components.
7254
+ let seenNonNullable = false;
7255
+ for (const t of (<UnionOrIntersectionType>type).types) {
7256
+ if (t.flags & TypeFlags.Nullable) {
7257
+ continue;
7258
+ }
7259
+ if (seenNonNullable) {
7260
+ return true;
7261
+ }
7262
+ seenNonNullable = true;
7263
+ }
7264
+ return false;
7265
+ }
7266
+
7227
7267
/**
7228
7268
* Compare two types and return
7229
7269
* * Ternary.True if they are related with no assumptions,
@@ -7258,7 +7298,7 @@ namespace ts {
7258
7298
// and intersection types are further deconstructed on the target side, we don't want to
7259
7299
// make the check again (as it might fail for a partial target type). Therefore we obtain
7260
7300
// the regular source type and proceed with that.
7261
- if (target.flags & TypeFlags.UnionOrIntersection ) {
7301
+ if (isUnionOrIntersectionTypeWithoutNullableConstituents( target) ) {
7262
7302
source = getRegularTypeOfObjectLiteral(source);
7263
7303
}
7264
7304
}
@@ -11334,13 +11374,7 @@ namespace ts {
11334
11374
}
11335
11375
11336
11376
function checkSpreadExpression(node: SpreadElement, contextualMapper?: TypeMapper): Type {
11337
- // It is usually not safe to call checkExpressionCached if we can be contextually typing.
11338
- // You can tell that we are contextually typing because of the contextualMapper parameter.
11339
- // While it is true that a spread element can have a contextual type, it does not do anything
11340
- // with this type. It is neither affected by it, nor does it propagate it to its operand.
11341
- // So the fact that contextualMapper is passed is not important, because the operand of a spread
11342
- // element is not contextually typed.
11343
- const arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
11377
+ const arrayOrIterableType = checkExpression(node.expression, contextualMapper);
11344
11378
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
11345
11379
}
11346
11380
@@ -11630,8 +11664,11 @@ namespace ts {
11630
11664
if (propertiesArray.length > 0) {
11631
11665
spread = getSpreadType(spread, createObjectLiteralType(), /*isFromObjectLiteral*/ true);
11632
11666
}
11633
- spread.flags |= propagatedFlags;
11634
- spread.symbol = node.symbol;
11667
+ if (spread.flags & TypeFlags.Object) {
11668
+ // only set the symbol and flags if this is a (fresh) object type
11669
+ spread.flags |= propagatedFlags;
11670
+ spread.symbol = node.symbol;
11671
+ }
11635
11672
return spread;
11636
11673
}
11637
11674
@@ -16573,6 +16610,10 @@ namespace ts {
16573
16610
}
16574
16611
}
16575
16612
16613
+ function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode {
16614
+ return node.dotDotDotToken ? getRestParameterElementType(node.type) : node.type;
16615
+ }
16616
+
16576
16617
/** Check the decorators of a node */
16577
16618
function checkDecorators(node: Node): void {
16578
16619
if (!node.decorators) {
@@ -16604,7 +16645,7 @@ namespace ts {
16604
16645
const constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
16605
16646
if (constructor) {
16606
16647
for (const parameter of constructor.parameters) {
16607
- markTypeNodeAsReferenced(parameter.type );
16648
+ markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck( parameter) );
16608
16649
}
16609
16650
}
16610
16651
break;
@@ -16613,15 +16654,17 @@ namespace ts {
16613
16654
case SyntaxKind.GetAccessor:
16614
16655
case SyntaxKind.SetAccessor:
16615
16656
for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
16616
- markTypeNodeAsReferenced(parameter.type );
16657
+ markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck( parameter) );
16617
16658
}
16618
16659
16619
16660
markTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
16620
16661
break;
16621
16662
16622
16663
case SyntaxKind.PropertyDeclaration:
16664
+ markTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(<ParameterDeclaration>node));
16665
+ break;
16623
16666
case SyntaxKind.Parameter:
16624
- markTypeNodeAsReferenced((<PropertyDeclaration | ParameterDeclaration >node).type);
16667
+ markTypeNodeAsReferenced((<PropertyDeclaration>node).type);
16625
16668
break;
16626
16669
}
16627
16670
}
@@ -18092,7 +18135,7 @@ namespace ts {
18092
18135
18093
18136
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
18094
18137
if (baseTypeNode) {
18095
- if (languageVersion < ScriptTarget.ES2015) {
18138
+ if (languageVersion < ScriptTarget.ES2015 && !isInAmbientContext(node) ) {
18096
18139
checkExternalEmitHelpers(baseTypeNode.parent, ExternalEmitHelpers.Extends);
18097
18140
}
18098
18141
0 commit comments