@@ -11460,7 +11460,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
11460
11460
// contextual type or, if the element itself is a binding pattern, with the type implied by that binding
11461
11461
// pattern.
11462
11462
const contextualType = isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType;
11463
- return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType)));
11463
+ return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, reportErrors ? CheckMode.Normal : CheckMode.Contextual , contextualType)));
11464
11464
}
11465
11465
if (isBindingPattern(element.name)) {
11466
11466
return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors);
@@ -11618,24 +11618,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
11618
11618
return false;
11619
11619
}
11620
11620
11621
- function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type {
11621
+ function getTypeOfVariableOrParameterOrProperty(symbol: Symbol, checkMode?: CheckMode ): Type {
11622
11622
const links = getSymbolLinks(symbol);
11623
11623
if (!links.type) {
11624
- const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol);
11624
+ const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol, checkMode );
11625
11625
// For a contextually typed parameter it is possible that a type has already
11626
11626
// been assigned (in assignTypeToParameterAndFixTypeParameters), and we want
11627
11627
// to preserve this type. In fact, we need to _prefer_ that type, but it won't
11628
11628
// be assigned until contextual typing is complete, so we need to defer in
11629
11629
// cases where contextual typing may take place.
11630
- if (!links.type && !isParameterOfContextSensitiveSignature(symbol)) {
11630
+ if (!links.type && !isParameterOfContextSensitiveSignature(symbol) && !checkMode ) {
11631
11631
links.type = type;
11632
11632
}
11633
11633
return type;
11634
11634
}
11635
11635
return links.type;
11636
11636
}
11637
11637
11638
- function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol): Type {
11638
+ function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol, checkMode?: CheckMode ): Type {
11639
11639
// Handle prototype property
11640
11640
if (symbol.flags & SymbolFlags.Prototype) {
11641
11641
return getTypeOfPrototypeProperty(symbol);
@@ -11678,6 +11678,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
11678
11678
if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) {
11679
11679
return getTypeOfFuncClassEnumModule(symbol);
11680
11680
}
11681
+
11682
+ // When trying to get the *contextual* type of a binding element, it's possible to fall in a loop and therefore
11683
+ // end up in a circularity-like situation. This is not a true circularity so we should not report such an error.
11684
+ // For example, here the looping could happen when trying to get the type of `a` (binding element):
11685
+ //
11686
+ // const { a, b = a } = { a: 0 }
11687
+ //
11688
+ if (isBindingElement(declaration) && checkMode === CheckMode.Contextual) {
11689
+ return errorType;
11690
+ }
11681
11691
return reportCircularityError(symbol);
11682
11692
}
11683
11693
let type: Type;
@@ -11750,6 +11760,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
11750
11760
if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) {
11751
11761
return getTypeOfFuncClassEnumModule(symbol);
11752
11762
}
11763
+
11764
+ // When trying to get the *contextual* type of a binding element, it's possible to fall in a loop and therefore
11765
+ // end up in a circularity-like situation. This is not a true circularity so we should not report such an error.
11766
+ // For example, here the looping could happen when trying to get the type of `a` (binding element):
11767
+ //
11768
+ // const { a, b = a } = { a: 0 }
11769
+ //
11770
+ if (isBindingElement(declaration) && checkMode === CheckMode.Contextual) {
11771
+ return type;
11772
+ }
11753
11773
return reportCircularityError(symbol);
11754
11774
}
11755
11775
return type;
@@ -12032,7 +12052,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
12032
12052
return getTypeOfSymbol(symbol);
12033
12053
}
12034
12054
12035
- function getTypeOfSymbol(symbol: Symbol): Type {
12055
+ function getTypeOfSymbol(symbol: Symbol, checkMode?: CheckMode ): Type {
12036
12056
const checkFlags = getCheckFlags(symbol);
12037
12057
if (checkFlags & CheckFlags.DeferredType) {
12038
12058
return getTypeOfSymbolWithDeferredType(symbol);
@@ -12047,7 +12067,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
12047
12067
return getTypeOfReverseMappedSymbol(symbol as ReverseMappedSymbol);
12048
12068
}
12049
12069
if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
12050
- return getTypeOfVariableOrParameterOrProperty(symbol);
12070
+ return getTypeOfVariableOrParameterOrProperty(symbol, checkMode );
12051
12071
}
12052
12072
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
12053
12073
return getTypeOfFuncClassEnumModule(symbol);
@@ -29069,8 +29089,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29069
29089
}
29070
29090
}
29071
29091
29072
- function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier) {
29073
- const type = getTypeOfSymbol(symbol);
29092
+ function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier, checkMode?: CheckMode ) {
29093
+ const type = getTypeOfSymbol(symbol, checkMode );
29074
29094
const declaration = symbol.valueDeclaration;
29075
29095
if (declaration) {
29076
29096
// If we have a non-rest binding element with no initializer declared as a const variable or a const-like
@@ -29233,7 +29253,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29233
29253
29234
29254
checkNestedBlockScopedBinding(node, symbol);
29235
29255
29236
- let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node);
29256
+ let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node, checkMode );
29237
29257
const assignmentKind = getAssignmentTargetKind(node);
29238
29258
29239
29259
if (assignmentKind) {
0 commit comments