@@ -3472,20 +3472,7 @@ namespace ts {
3472
3472
}
3473
3473
3474
3474
if (!popTypeResolution()) {
3475
- if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
3476
- // Variable has type annotation that circularly references the variable itself
3477
- type = unknownType;
3478
- error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
3479
- symbolToString(symbol));
3480
- }
3481
- else {
3482
- // Variable has initializer that circularly references the variable itself
3483
- type = anyType;
3484
- if (compilerOptions.noImplicitAny) {
3485
- error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
3486
- symbolToString(symbol));
3487
- }
3488
- }
3475
+ type = reportCircularityError(symbol);
3489
3476
}
3490
3477
links.type = type;
3491
3478
}
@@ -3619,11 +3606,33 @@ namespace ts {
3619
3606
function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
3620
3607
const links = getSymbolLinks(symbol);
3621
3608
if (!links.type) {
3622
- links.type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
3609
+ if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
3610
+ return unknownType;
3611
+ }
3612
+ let type = instantiateType(getTypeOfSymbol(links.target), links.mapper);
3613
+ if (!popTypeResolution()) {
3614
+ type = reportCircularityError(symbol);
3615
+ }
3616
+ links.type = type;
3623
3617
}
3624
3618
return links.type;
3625
3619
}
3626
3620
3621
+ function reportCircularityError(symbol: Symbol) {
3622
+ // Check if variable has type annotation that circularly references the variable itself
3623
+ if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
3624
+ error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
3625
+ symbolToString(symbol));
3626
+ return unknownType;
3627
+ }
3628
+ // Otherwise variable has initializer that circularly references the variable itself
3629
+ if (compilerOptions.noImplicitAny) {
3630
+ error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
3631
+ symbolToString(symbol));
3632
+ }
3633
+ return anyType;
3634
+ }
3635
+
3627
3636
function getTypeOfSymbol(symbol: Symbol): Type {
3628
3637
if (symbol.flags & SymbolFlags.Instantiated) {
3629
3638
return getTypeOfInstantiatedSymbol(symbol);
@@ -5270,28 +5279,9 @@ namespace ts {
5270
5279
return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint;
5271
5280
}
5272
5281
5273
- function getConstraintOfIndexedAccess(type: IndexedAccessType): Type {
5274
- // The constraint of T[K], where T is an object, union, or intersection type,
5275
- // is the type of the string index signature of T, if any.
5276
- if (type.objectType.flags & TypeFlags.StructuredType) {
5277
- return getIndexTypeOfType(type.objectType, IndexKind.String);
5278
- }
5279
- // The constraint of T[K], where T is a type variable, is A[K], where A is the
5280
- // apparent type of T.
5281
- if (type.objectType.flags & TypeFlags.TypeVariable) {
5282
- const apparentType = getApparentTypeOfTypeVariable(<TypeVariable>type.objectType);
5283
- if (apparentType !== emptyObjectType) {
5284
- return isTypeOfKind((<IndexedAccessType>type).indexType, TypeFlags.StringLike) ?
5285
- getIndexedAccessType(apparentType, (<IndexedAccessType>type).indexType) :
5286
- getIndexTypeOfType(apparentType, IndexKind.String);
5287
- }
5288
- }
5289
- return undefined;
5290
- }
5291
-
5292
5282
function getConstraintOfTypeVariable(type: TypeVariable): Type {
5293
5283
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) :
5294
- type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess (<IndexedAccessType>type) :
5284
+ type.flags & TypeFlags.IndexedAccess ? (<IndexedAccessType>type).constraint :
5295
5285
undefined;
5296
5286
}
5297
5287
@@ -5970,6 +5960,24 @@ namespace ts {
5970
5960
const type = <IndexedAccessType>createType(TypeFlags.IndexedAccess);
5971
5961
type.objectType = objectType;
5972
5962
type.indexType = indexType;
5963
+ // We eagerly compute the constraint of the indexed access type such that circularity
5964
+ // errors are immediately caught and reported. For example, class C { x: this["x"] }
5965
+ // becomes an error only when the constraint is eagerly computed.
5966
+ if (type.objectType.flags & TypeFlags.StructuredType) {
5967
+ // The constraint of T[K], where T is an object, union, or intersection type,
5968
+ // is the type of the string index signature of T, if any.
5969
+ type.constraint = getIndexTypeOfType(type.objectType, IndexKind.String);
5970
+ }
5971
+ else if (type.objectType.flags & TypeFlags.TypeVariable) {
5972
+ // The constraint of T[K], where T is a type variable, is A[K], where A is the
5973
+ // apparent type of T.
5974
+ const apparentType = getApparentTypeOfTypeVariable(<TypeVariable>type.objectType);
5975
+ if (apparentType !== emptyObjectType) {
5976
+ type.constraint = isTypeOfKind((<IndexedAccessType>type).indexType, TypeFlags.StringLike) ?
5977
+ getIndexedAccessType(apparentType, (<IndexedAccessType>type).indexType) :
5978
+ getIndexTypeOfType(apparentType, IndexKind.String);
5979
+ }
5980
+ }
5973
5981
return type;
5974
5982
}
5975
5983
@@ -7312,9 +7320,8 @@ namespace ts {
7312
7320
}
7313
7321
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
7314
7322
// A is the apparent type of S.
7315
- const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>target);
7316
- if (constraint) {
7317
- if (result = isRelatedTo(source, constraint, reportErrors)) {
7323
+ if ((<IndexedAccessType>target).constraint) {
7324
+ if (result = isRelatedTo(source, (<IndexedAccessType>target).constraint, reportErrors)) {
7318
7325
errorInfo = saveErrorInfo;
7319
7326
return result;
7320
7327
}
@@ -7352,9 +7359,8 @@ namespace ts {
7352
7359
else if (source.flags & TypeFlags.IndexedAccess) {
7353
7360
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
7354
7361
// A is the apparent type of S.
7355
- const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>source);
7356
- if (constraint) {
7357
- if (result = isRelatedTo(constraint, target, reportErrors)) {
7362
+ if ((<IndexedAccessType>source).constraint) {
7363
+ if (result = isRelatedTo((<IndexedAccessType>source).constraint, target, reportErrors)) {
7358
7364
errorInfo = saveErrorInfo;
7359
7365
return result;
7360
7366
}
0 commit comments