@@ -196,6 +196,7 @@ namespace ts {
196
196
Source = 1 << 0,
197
197
Target = 1 << 1,
198
198
PropertyCheck = 1 << 2,
199
+ InPropertyCheck = 1 << 3,
199
200
}
200
201
201
202
const enum MappedTypeModifiers {
@@ -6132,7 +6133,8 @@ namespace ts {
6132
6133
// Each overload becomes a separate function declaration, in order
6133
6134
const decl = signatureToSignatureDeclarationHelper(sig, SyntaxKind.FunctionDeclaration, context, includePrivateSymbol, bundled) as FunctionDeclaration;
6134
6135
decl.name = createIdentifier(localName);
6135
- addResult(setTextRange(decl, sig.declaration), modifierFlags);
6136
+ // for expressions assigned to `var`s, use the `var` as the text range
6137
+ addResult(setTextRange(decl, sig.declaration && isVariableDeclaration(sig.declaration.parent) && sig.declaration.parent.parent || sig.declaration), modifierFlags);
6136
6138
}
6137
6139
// Module symbol emit will take care of module-y members, provided it has exports
6138
6140
if (!(symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && !!symbol.exports && !!symbol.exports.size)) {
@@ -6210,14 +6212,18 @@ namespace ts {
6210
6212
];
6211
6213
const symbolProps = getPropertiesOfType(classType);
6212
6214
const publicSymbolProps = filter(symbolProps, s => {
6215
+ // `valueDeclaration` could be undefined if inherited from
6216
+ // a union/intersection base type, but inherited properties
6217
+ // don't matter here.
6213
6218
const valueDecl = s.valueDeclaration;
6214
- Debug.assertIsDefined(valueDecl);
6215
- return !(isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name));
6219
+ return valueDecl && !(isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name));
6216
6220
});
6217
6221
const hasPrivateIdentifier = some(symbolProps, s => {
6222
+ // `valueDeclaration` could be undefined if inherited from
6223
+ // a union/intersection base type, but inherited properties
6224
+ // don't matter here.
6218
6225
const valueDecl = s.valueDeclaration;
6219
- Debug.assertIsDefined(valueDecl);
6220
- return isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name);
6226
+ return valueDecl && isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name);
6221
6227
});
6222
6228
// Boil down all private properties into a single one.
6223
6229
const privateProperties = hasPrivateIdentifier ?
@@ -10419,7 +10425,7 @@ namespace ts {
10419
10425
if (!firstValueDeclaration) {
10420
10426
firstValueDeclaration = prop.valueDeclaration;
10421
10427
}
10422
- else if (prop.valueDeclaration !== firstValueDeclaration) {
10428
+ else if (prop.valueDeclaration && prop.valueDeclaration !== firstValueDeclaration) {
10423
10429
hasNonUniformValueDeclaration = true;
10424
10430
}
10425
10431
declarations = addRange(declarations, prop.declarations);
@@ -14545,6 +14551,16 @@ namespace ts {
14545
14551
}
14546
14552
}
14547
14553
14554
+ function checkExpressionForMutableLocationWithContextualType(next: Expression, sourcePropType: Type) {
14555
+ next.contextualType = sourcePropType;
14556
+ try {
14557
+ return checkExpressionForMutableLocation(next, CheckMode.Contextual, sourcePropType);
14558
+ }
14559
+ finally {
14560
+ next.contextualType = undefined;
14561
+ }
14562
+ }
14563
+
14548
14564
type ElaborationIterator = IterableIterator<{ errorNode: Node, innerExpression: Expression | undefined, nameType: Type, errorMessage?: DiagnosticMessage | undefined }>;
14549
14565
/**
14550
14566
* For every element returned from the iterator, checks that element to issue an error on a property of that element's type
@@ -14575,7 +14591,7 @@ namespace ts {
14575
14591
// Issue error on the prop itself, since the prop couldn't elaborate the error
14576
14592
const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {};
14577
14593
// Use the expression type, if available
14578
- const specificSource = next ? checkExpressionForMutableLocation (next, CheckMode.Normal , sourcePropType) : sourcePropType;
14594
+ const specificSource = next ? checkExpressionForMutableLocationWithContextualType (next, sourcePropType) : sourcePropType;
14579
14595
const result = checkTypeRelatedTo(specificSource, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj);
14580
14596
if (result && specificSource !== sourcePropType) {
14581
14597
// If for whatever reason the expression type doesn't yield an error, make sure we still issue an error on the sourcePropType
@@ -15230,6 +15246,7 @@ namespace ts {
15230
15246
let overrideNextErrorInfo = 0; // How many `reportRelationError` calls should be skipped in the elaboration pyramid
15231
15247
let lastSkippedInfo: [Type, Type] | undefined;
15232
15248
let incompatibleStack: [DiagnosticMessage, (string | number)?, (string | number)?, (string | number)?, (string | number)?][] = [];
15249
+ let inPropertyCheck = false;
15233
15250
15234
15251
Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
15235
15252
@@ -15238,7 +15255,7 @@ namespace ts {
15238
15255
reportIncompatibleStack();
15239
15256
}
15240
15257
if (overflow) {
15241
- const diag = error(errorNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
15258
+ const diag = error(errorNode || currentNode , Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
15242
15259
if (errorOutputContainer) {
15243
15260
(errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
15244
15261
}
@@ -15665,10 +15682,15 @@ namespace ts {
15665
15682
// function foo<T extends object>(x: { a?: string }, y: T & { a: boolean }) {
15666
15683
// x = y; // Mismatched property in source intersection
15667
15684
// }
15668
- if (result && (
15685
+ //
15686
+ // We suppress recursive intersection property checks because they can generate lots of work when relating
15687
+ // recursive intersections that are structurally similar but not exactly identical. See #37854.
15688
+ if (result && !inPropertyCheck && (
15669
15689
target.flags & TypeFlags.Intersection && (isPerformingExcessPropertyChecks || isPerformingCommonPropertyChecks) ||
15670
15690
isNonGenericObjectType(target) && source.flags & TypeFlags.Intersection && getApparentType(source).flags & TypeFlags.StructuredType && !some((<IntersectionType>source).types, t => !!(getObjectFlags(t) & ObjectFlags.NonInferrableType)))) {
15691
+ inPropertyCheck = true;
15671
15692
result &= recursiveTypeRelatedTo(source, target, reportErrors, IntersectionState.PropertyCheck);
15693
+ inPropertyCheck = false;
15672
15694
}
15673
15695
15674
15696
if (!result && reportErrors) {
@@ -15965,7 +15987,7 @@ namespace ts {
15965
15987
if (overflow) {
15966
15988
return Ternary.False;
15967
15989
}
15968
- const id = getRelationKey(source, target, intersectionState, relation);
15990
+ const id = getRelationKey(source, target, intersectionState | (inPropertyCheck ? IntersectionState.InPropertyCheck : 0) , relation);
15969
15991
const entry = relation.get(id);
15970
15992
if (entry !== undefined) {
15971
15993
if (reportErrors && entry & RelationComparisonResult.Failed && !(entry & RelationComparisonResult.Reported)) {
@@ -27243,7 +27265,7 @@ namespace ts {
27243
27265
}
27244
27266
27245
27267
const functionFlags = getFunctionFlags(func);
27246
- const type = returnType && getReturnOrPromisedType (returnType, functionFlags);
27268
+ const type = returnType && unwrapReturnType (returnType, functionFlags);
27247
27269
27248
27270
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
27249
27271
if (type && maybeTypeOfKind(type, TypeFlags.Any | TypeFlags.Void)) {
@@ -27363,14 +27385,6 @@ namespace ts {
27363
27385
}
27364
27386
}
27365
27387
27366
- function getReturnOrPromisedType(type: Type | undefined, functionFlags: FunctionFlags) {
27367
- const isGenerator = !!(functionFlags & FunctionFlags.Generator);
27368
- const isAsync = !!(functionFlags & FunctionFlags.Async);
27369
- return type && isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsync) || errorType :
27370
- type && isAsync ? getAwaitedType(type) || errorType :
27371
- type;
27372
- }
27373
-
27374
27388
function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
27375
27389
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
27376
27390
@@ -27398,7 +27412,7 @@ namespace ts {
27398
27412
// check assignability of the awaited type of the expression body against the promised type of
27399
27413
// its return type annotation.
27400
27414
const exprType = checkExpression(node.body);
27401
- const returnOrPromisedType = getReturnOrPromisedType (returnType, functionFlags);
27415
+ const returnOrPromisedType = returnType && unwrapReturnType (returnType, functionFlags);
27402
27416
if (returnOrPromisedType) {
27403
27417
if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function
27404
27418
const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
@@ -32686,8 +32700,8 @@ namespace ts {
32686
32700
function unwrapReturnType(returnType: Type, functionFlags: FunctionFlags) {
32687
32701
const isGenerator = !!(functionFlags & FunctionFlags.Generator);
32688
32702
const isAsync = !!(functionFlags & FunctionFlags.Async);
32689
- return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) || errorType :
32690
- isAsync ? getPromisedTypeOfPromise (returnType) || errorType :
32703
+ return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) ?? errorType :
32704
+ isAsync ? getAwaitedType (returnType) ?? errorType :
32691
32705
returnType;
32692
32706
}
32693
32707
@@ -32724,7 +32738,7 @@ namespace ts {
32724
32738
}
32725
32739
}
32726
32740
else if (getReturnTypeFromAnnotation(func)) {
32727
- const unwrappedReturnType = unwrapReturnType(returnType, functionFlags);
32741
+ const unwrappedReturnType = unwrapReturnType(returnType, functionFlags) ?? returnType ;
32728
32742
const unwrappedExprType = functionFlags & FunctionFlags.Async
32729
32743
? checkAwaitedType(exprType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)
32730
32744
: exprType;
@@ -32936,6 +32950,10 @@ namespace ts {
32936
32950
const propDeclaration = prop.valueDeclaration;
32937
32951
const name = propDeclaration && getNameOfDeclaration(propDeclaration);
32938
32952
32953
+ if (name && isPrivateIdentifier(name)) {
32954
+ return;
32955
+ }
32956
+
32939
32957
// index is numeric and property name is not valid numeric literal
32940
32958
if (indexKind === IndexKind.Number && !(name ? isNumericName(name) : isNumericLiteralName(prop.escapedName))) {
32941
32959
return;
@@ -34015,7 +34033,7 @@ namespace ts {
34015
34033
return false;
34016
34034
}
34017
34035
if (inAmbientExternalModule && isExternalModuleNameRelative(moduleName.text)) {
34018
- // we have already reported errors on top level imports\ exports in external module augmentations in checkModuleDeclaration
34036
+ // we have already reported errors on top level imports/ exports in external module augmentations in checkModuleDeclaration
34019
34037
// no need to do this again.
34020
34038
if (!isTopLevelInExternalModuleAugmentation(node)) {
34021
34039
// TypeScript 1.0 spec (April 2013): 12.1.6
@@ -34151,16 +34169,10 @@ namespace ts {
34151
34169
34152
34170
checkGrammarExportDeclaration(node);
34153
34171
if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
34154
- if (node.exportClause) {
34172
+ if (node.exportClause && !isNamespaceExport(node.exportClause) ) {
34155
34173
// export { x, y }
34156
34174
// export { x, y } from "foo"
34157
- if (isNamedExports(node.exportClause)) {
34158
- forEach(node.exportClause.elements, checkExportSpecifier);
34159
- }
34160
- else if(!isNamespaceExport(node.exportClause)) {
34161
- checkImportBinding(node.exportClause);
34162
- }
34163
-
34175
+ forEach(node.exportClause.elements, checkExportSpecifier);
34164
34176
const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent);
34165
34177
const inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === SyntaxKind.ModuleBlock &&
34166
34178
!node.moduleSpecifier && node.flags & NodeFlags.Ambient;
@@ -34174,7 +34186,9 @@ namespace ts {
34174
34186
if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) {
34175
34187
error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
34176
34188
}
34177
-
34189
+ else if (node.exportClause) {
34190
+ checkAliasSymbol(node.exportClause);
34191
+ }
34178
34192
if (moduleKind !== ModuleKind.System && moduleKind < ModuleKind.ES2015) {
34179
34193
checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar);
34180
34194
}
0 commit comments