Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit df7ed82

Browse files
authoredMar 28, 2022
Revise accessor resolution logic and error reporting (microsoft#48459)
* Revise accessor resolution logic and error reporting * Accept new baselines * Update isTypeElement * Add tests
1 parent c720ad6 commit df7ed82

9 files changed

+330
-127
lines changed
 

‎src/compiler/checker.ts

Lines changed: 72 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ namespace ts {
172172
EnumTagType,
173173
ResolvedTypeArguments,
174174
ResolvedBaseTypes,
175+
WriteType,
175176
}
176177

177178
const enum CheckMode {
@@ -8519,6 +8520,8 @@ namespace ts {
85198520
return !!(target as TypeReference).resolvedTypeArguments;
85208521
case TypeSystemPropertyName.ResolvedBaseTypes:
85218522
return !!(target as InterfaceType).baseTypesResolved;
8523+
case TypeSystemPropertyName.WriteType:
8524+
return !!getSymbolLinks(target as Symbol).writeType;
85228525
}
85238526
return Debug.assertNever(propertyName);
85248527
}
@@ -9502,6 +9505,11 @@ namespace ts {
95029505
}
95039506
return getWidenedType(getWidenedLiteralType(checkExpression(declaration.statements[0].expression)));
95049507
}
9508+
if (isAccessor(declaration)) {
9509+
// Binding of certain patterns in JS code will occasionally mark symbols as both properties
9510+
// and accessors. Here we dispatch to accessor resolution if needed.
9511+
return getTypeOfAccessors(symbol);
9512+
}
95059513

95069514
// Handle variable, parameter or property
95079515
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
@@ -9567,9 +9575,6 @@ namespace ts {
95679575
else if (isEnumMember(declaration)) {
95689576
type = getTypeOfEnumMember(symbol);
95699577
}
9570-
else if (isAccessor(declaration)) {
9571-
type = resolveTypeOfAccessors(symbol) || Debug.fail("Non-write accessor resolution must always produce a type");
9572-
}
95739578
else {
95749579
return Debug.fail("Unhandled declaration kind! " + Debug.formatSyntaxKind(declaration.kind) + " for " + Debug.formatSymbol(symbol));
95759580
}
@@ -9614,97 +9619,62 @@ namespace ts {
96149619

96159620
function getTypeOfAccessors(symbol: Symbol): Type {
96169621
const links = getSymbolLinks(symbol);
9617-
return links.type || (links.type = getTypeOfAccessorsWorker(symbol) || Debug.fail("Read type of accessor must always produce a type"));
9618-
}
9619-
9620-
function getTypeOfSetAccessor(symbol: Symbol): Type | undefined {
9621-
const links = getSymbolLinks(symbol);
9622-
return links.writeType || (links.writeType = getTypeOfAccessorsWorker(symbol, /*writing*/ true));
9623-
}
9624-
9625-
function getTypeOfAccessorsWorker(symbol: Symbol, writing = false): Type | undefined {
9626-
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
9627-
return errorType;
9628-
}
9629-
9630-
let type = resolveTypeOfAccessors(symbol, writing);
9631-
if (!popTypeResolution()) {
9622+
if (!links.type) {
9623+
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
9624+
return errorType;
9625+
}
96329626
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
9633-
if (getter) {
9634-
if (getEffectiveTypeAnnotationNode(getter)) {
9635-
error(getter.name, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
9627+
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
9628+
// We try to resolve a getter type annotation, a setter type annotation, or a getter function
9629+
// body return type inference, in that order.
9630+
let type = getter && isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) ||
9631+
getAnnotatedAccessorType(getter) ||
9632+
getAnnotatedAccessorType(setter) ||
9633+
getter && getter.body && getReturnTypeFromBody(getter);
9634+
if (!type) {
9635+
if (setter && !isPrivateWithinAmbient(setter)) {
9636+
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
9637+
}
9638+
else if (getter && !isPrivateWithinAmbient(getter)) {
9639+
errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
9640+
}
9641+
type = anyType;
9642+
}
9643+
if (!popTypeResolution()) {
9644+
if (getAnnotatedAccessorTypeNode(getter)) {
9645+
error(getter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
96369646
}
9637-
else if (noImplicitAny) {
9647+
else if (getAnnotatedAccessorTypeNode(setter)) {
9648+
error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
9649+
}
9650+
else if (getter && noImplicitAny) {
96389651
error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
96399652
}
9653+
type = anyType;
96409654
}
9641-
type = anyType;
9655+
links.type = type;
96429656
}
9643-
return type;
9657+
return links.type;
96449658
}
96459659

9646-
function resolveTypeOfAccessors(symbol: Symbol, writing = false) {
9647-
const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
9648-
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
9649-
9650-
// For write operations, prioritize type annotations on the setter
9651-
if (writing) {
9652-
const setterType = getAnnotatedAccessorType(setter);
9653-
if (setterType) {
9654-
return instantiateTypeIfNeeded(setterType, symbol);
9655-
}
9656-
}
9657-
// Else defer to the getter type
9658-
9659-
if (getter && isInJSFile(getter)) {
9660-
const jsDocType = getTypeForDeclarationFromJSDocComment(getter);
9661-
if (jsDocType) {
9662-
return instantiateTypeIfNeeded(jsDocType, symbol);
9663-
}
9664-
}
9665-
9666-
// Try to see if the user specified a return type on the get-accessor.
9667-
const getterType = getAnnotatedAccessorType(getter);
9668-
if (getterType) {
9669-
return instantiateTypeIfNeeded(getterType, symbol);
9670-
}
9671-
9672-
// If the user didn't specify a return type, try to use the set-accessor's parameter type.
9673-
const setterType = getAnnotatedAccessorType(setter);
9674-
if (setterType) {
9675-
return setterType;
9676-
}
9677-
9678-
// If there are no specified types, try to infer it from the body of the get accessor if it exists.
9679-
if (getter && getter.body) {
9680-
const returnTypeFromBody = getReturnTypeFromBody(getter);
9681-
return instantiateTypeIfNeeded(returnTypeFromBody, symbol);
9682-
}
9683-
9684-
// Otherwise, fall back to 'any'.
9685-
if (setter) {
9686-
if (!isPrivateWithinAmbient(setter)) {
9687-
errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
9688-
}
9689-
return anyType;
9690-
}
9691-
else if (getter) {
9692-
Debug.assert(!!getter, "there must exist a getter as we are current checking either setter or getter in this function");
9693-
if (!isPrivateWithinAmbient(getter)) {
9694-
errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
9660+
function getWriteTypeOfAccessors(symbol: Symbol): Type {
9661+
const links = getSymbolLinks(symbol);
9662+
if (!links.writeType) {
9663+
if (!pushTypeResolution(symbol, TypeSystemPropertyName.WriteType)) {
9664+
return errorType;
96959665
}
9696-
return anyType;
9697-
}
9698-
return undefined;
9699-
9700-
function instantiateTypeIfNeeded(type: Type, symbol: Symbol) {
9701-
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
9702-
const links = getSymbolLinks(symbol);
9703-
return instantiateType(type, links.mapper);
9666+
const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
9667+
let writeType = getAnnotatedAccessorType(setter);
9668+
if (!popTypeResolution()) {
9669+
if (getAnnotatedAccessorTypeNode(setter)) {
9670+
error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
9671+
}
9672+
writeType = anyType;
97049673
}
9705-
9706-
return type;
9674+
// Absent an explicit setter type annotation we use the read type of the accessor.
9675+
links.writeType = writeType || getTypeOfAccessors(symbol);
97079676
}
9677+
return links.writeType;
97089678
}
97099679

97109680
function getBaseTypeVariableOfClass(symbol: Symbol) {
@@ -9792,17 +9762,12 @@ namespace ts {
97929762

97939763
function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
97949764
const links = getSymbolLinks(symbol);
9795-
if (!links.type) {
9796-
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
9797-
return links.type = errorType;
9798-
}
9799-
let type = instantiateType(getTypeOfSymbol(links.target!), links.mapper);
9800-
if (!popTypeResolution()) {
9801-
type = reportCircularityError(symbol);
9802-
}
9803-
links.type = type;
9804-
}
9805-
return links.type;
9765+
return links.type || (links.type = instantiateType(getTypeOfSymbol(links.target!), links.mapper));
9766+
}
9767+
9768+
function getWriteTypeOfInstantiatedSymbol(symbol: Symbol): Type {
9769+
const links = getSymbolLinks(symbol);
9770+
return links.writeType || (links.writeType = instantiateType(getWriteTypeOfSymbol(links.target!), links.mapper));
98069771
}
98079772

98089773
function reportCircularityError(symbol: Symbol) {
@@ -9845,36 +9810,23 @@ namespace ts {
98459810
}
98469811

98479812
/**
9848-
* Distinct write types come only from set accessors, but union and intersection
9849-
* properties deriving from set accessors will either pre-compute or defer the
9850-
* union or intersection of the writeTypes of their constituents. To account for
9851-
* this, we will assume that any deferred type or transient symbol may have a
9852-
* `writeType` (or a deferred write type ready to be computed) that should be
9853-
* used before looking for set accessor declarations.
9813+
* Distinct write types come only from set accessors, but synthetic union and intersection
9814+
* properties deriving from set accessors will either pre-compute or defer the union or
9815+
* intersection of the writeTypes of their constituents.
98549816
*/
98559817
function getWriteTypeOfSymbol(symbol: Symbol): Type {
98569818
const checkFlags = getCheckFlags(symbol);
9857-
if (checkFlags & CheckFlags.DeferredType) {
9858-
const writeType = getWriteTypeOfSymbolWithDeferredType(symbol);
9859-
if (writeType) {
9860-
return writeType;
9861-
}
9862-
}
9863-
if (symbol.flags & SymbolFlags.Transient) {
9864-
const { writeType } = symbol as TransientSymbol;
9865-
if (writeType) {
9866-
return writeType;
9867-
}
9819+
if (symbol.flags & SymbolFlags.Property) {
9820+
return checkFlags & CheckFlags.SyntheticProperty ?
9821+
checkFlags & CheckFlags.DeferredType ?
9822+
getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) :
9823+
(symbol as TransientSymbol).writeType || (symbol as TransientSymbol).type! :
9824+
getTypeOfSymbol(symbol);
98689825
}
9869-
return getSetAccessorTypeOfSymbol(symbol);
9870-
}
9871-
9872-
function getSetAccessorTypeOfSymbol(symbol: Symbol): Type {
98739826
if (symbol.flags & SymbolFlags.Accessor) {
9874-
const type = getTypeOfSetAccessor(symbol);
9875-
if (type) {
9876-
return type;
9877-
}
9827+
return checkFlags & CheckFlags.Instantiated ?
9828+
getWriteTypeOfInstantiatedSymbol(symbol) :
9829+
getWriteTypeOfAccessors(symbol);
98789830
}
98799831
return getTypeOfSymbol(symbol);
98809832
}
@@ -25237,7 +25189,7 @@ namespace ts {
2523725189
}
2523825190
}
2523925191
if (isDeclarationName(location) && isSetAccessor(location.parent) && getAnnotatedAccessorTypeNode(location.parent)) {
25240-
return resolveTypeOfAccessors(location.parent.symbol, /*writing*/ true)!;
25192+
return getWriteTypeOfAccessors(location.parent.symbol);
2524125193
}
2524225194
// The location isn't a reference to the given symbol, meaning we're being asked
2524325195
// a hypothetical question of what type the symbol would have if there was a reference

‎src/compiler/utilitiesPublic.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,9 @@ namespace ts {
13351335
|| kind === SyntaxKind.CallSignature
13361336
|| kind === SyntaxKind.PropertySignature
13371337
|| kind === SyntaxKind.MethodSignature
1338-
|| kind === SyntaxKind.IndexSignature;
1338+
|| kind === SyntaxKind.IndexSignature
1339+
|| kind === SyntaxKind.GetAccessor
1340+
|| kind === SyntaxKind.SetAccessor;
13391341
}
13401342

13411343
export function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
tests/cases/compiler/circularAccessorAnnotations.ts(2,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
2+
tests/cases/compiler/circularAccessorAnnotations.ts(6,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
3+
tests/cases/compiler/circularAccessorAnnotations.ts(15,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
4+
tests/cases/compiler/circularAccessorAnnotations.ts(19,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
5+
6+
7+
==== tests/cases/compiler/circularAccessorAnnotations.ts (4 errors) ====
8+
declare const c1: {
9+
get foo(): typeof c1.foo;
10+
~~~
11+
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
12+
}
13+
14+
declare const c2: {
15+
set foo(value: typeof c2.foo);
16+
~~~
17+
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
18+
}
19+
20+
declare const c3: {
21+
get foo(): string;
22+
set foo(value: typeof c3.foo);
23+
}
24+
25+
type T1 = {
26+
get foo(): T1["foo"];
27+
~~~
28+
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
29+
}
30+
31+
type T2 = {
32+
set foo(value: T2["foo"]);
33+
~~~
34+
!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
35+
}
36+
37+
type T3 = {
38+
get foo(): string;
39+
set foo(value: T3["foo"]);
40+
}
41+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//// [circularAccessorAnnotations.ts]
2+
declare const c1: {
3+
get foo(): typeof c1.foo;
4+
}
5+
6+
declare const c2: {
7+
set foo(value: typeof c2.foo);
8+
}
9+
10+
declare const c3: {
11+
get foo(): string;
12+
set foo(value: typeof c3.foo);
13+
}
14+
15+
type T1 = {
16+
get foo(): T1["foo"];
17+
}
18+
19+
type T2 = {
20+
set foo(value: T2["foo"]);
21+
}
22+
23+
type T3 = {
24+
get foo(): string;
25+
set foo(value: T3["foo"]);
26+
}
27+
28+
29+
//// [circularAccessorAnnotations.js]
30+
"use strict";
31+
32+
33+
//// [circularAccessorAnnotations.d.ts]
34+
declare const c1: {
35+
get foo(): typeof c1.foo;
36+
};
37+
declare const c2: {
38+
set foo(value: typeof c2.foo);
39+
};
40+
declare const c3: {
41+
get foo(): string;
42+
set foo(value: typeof c3.foo);
43+
};
44+
declare type T1 = {
45+
get foo(): T1["foo"];
46+
};
47+
declare type T2 = {
48+
set foo(value: T2["foo"]);
49+
};
50+
declare type T3 = {
51+
get foo(): string;
52+
set foo(value: T3["foo"]);
53+
};
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
=== tests/cases/compiler/circularAccessorAnnotations.ts ===
2+
declare const c1: {
3+
>c1 : Symbol(c1, Decl(circularAccessorAnnotations.ts, 0, 13))
4+
5+
get foo(): typeof c1.foo;
6+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 0, 19))
7+
>c1.foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 0, 19))
8+
>c1 : Symbol(c1, Decl(circularAccessorAnnotations.ts, 0, 13))
9+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 0, 19))
10+
}
11+
12+
declare const c2: {
13+
>c2 : Symbol(c2, Decl(circularAccessorAnnotations.ts, 4, 13))
14+
15+
set foo(value: typeof c2.foo);
16+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 4, 19))
17+
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 5, 12))
18+
>c2.foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 4, 19))
19+
>c2 : Symbol(c2, Decl(circularAccessorAnnotations.ts, 4, 13))
20+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 4, 19))
21+
}
22+
23+
declare const c3: {
24+
>c3 : Symbol(c3, Decl(circularAccessorAnnotations.ts, 8, 13))
25+
26+
get foo(): string;
27+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
28+
29+
set foo(value: typeof c3.foo);
30+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
31+
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 10, 12))
32+
>c3.foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
33+
>c3 : Symbol(c3, Decl(circularAccessorAnnotations.ts, 8, 13))
34+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 8, 19), Decl(circularAccessorAnnotations.ts, 9, 22))
35+
}
36+
37+
type T1 = {
38+
>T1 : Symbol(T1, Decl(circularAccessorAnnotations.ts, 11, 1))
39+
40+
get foo(): T1["foo"];
41+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 13, 11))
42+
>T1 : Symbol(T1, Decl(circularAccessorAnnotations.ts, 11, 1))
43+
}
44+
45+
type T2 = {
46+
>T2 : Symbol(T2, Decl(circularAccessorAnnotations.ts, 15, 1))
47+
48+
set foo(value: T2["foo"]);
49+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 17, 11))
50+
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 18, 12))
51+
>T2 : Symbol(T2, Decl(circularAccessorAnnotations.ts, 15, 1))
52+
}
53+
54+
type T3 = {
55+
>T3 : Symbol(T3, Decl(circularAccessorAnnotations.ts, 19, 1))
56+
57+
get foo(): string;
58+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 21, 11), Decl(circularAccessorAnnotations.ts, 22, 22))
59+
60+
set foo(value: T3["foo"]);
61+
>foo : Symbol(foo, Decl(circularAccessorAnnotations.ts, 21, 11), Decl(circularAccessorAnnotations.ts, 22, 22))
62+
>value : Symbol(value, Decl(circularAccessorAnnotations.ts, 23, 12))
63+
>T3 : Symbol(T3, Decl(circularAccessorAnnotations.ts, 19, 1))
64+
}
65+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
=== tests/cases/compiler/circularAccessorAnnotations.ts ===
2+
declare const c1: {
3+
>c1 : { readonly foo: any; }
4+
5+
get foo(): typeof c1.foo;
6+
>foo : any
7+
>c1.foo : any
8+
>c1 : { readonly foo: any; }
9+
>foo : any
10+
}
11+
12+
declare const c2: {
13+
>c2 : { foo: any; }
14+
15+
set foo(value: typeof c2.foo);
16+
>foo : any
17+
>value : any
18+
>c2.foo : any
19+
>c2 : { foo: any; }
20+
>foo : any
21+
}
22+
23+
declare const c3: {
24+
>c3 : { foo: string; }
25+
26+
get foo(): string;
27+
>foo : string
28+
29+
set foo(value: typeof c3.foo);
30+
>foo : string
31+
>value : string
32+
>c3.foo : string
33+
>c3 : { foo: string; }
34+
>foo : string
35+
}
36+
37+
type T1 = {
38+
>T1 : T1
39+
40+
get foo(): T1["foo"];
41+
>foo : any
42+
}
43+
44+
type T2 = {
45+
>T2 : T2
46+
47+
set foo(value: T2["foo"]);
48+
>foo : any
49+
>value : any
50+
}
51+
52+
type T3 = {
53+
>T3 : T3
54+
55+
get foo(): string;
56+
>foo : string
57+
58+
set foo(value: T3["foo"]);
59+
>foo : string
60+
>value : string
61+
}
62+

‎tests/baselines/reference/circularIndexedAccessErrors.errors.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(2,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
2-
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(6,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
2+
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(11,11): error TS2589: Type instantiation is excessively deep and possibly infinite.
33
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(18,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
44
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(22,5): error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
55
tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(37,24): error TS2313: Type parameter 'T' has a circular constraint.
@@ -15,13 +15,13 @@ tests/cases/conformance/types/keyof/circularIndexedAccessErrors.ts(37,30): error
1515

1616
type T2<K extends "x" | "y"> = {
1717
x: T2<K>[K]; // Error
18-
~
19-
!!! error TS2502: 'x' is referenced directly or indirectly in its own type annotation.
2018
y: number;
2119
}
2220

2321
declare let x2: T2<"x">;
2422
let x2x = x2.x;
23+
~~~~
24+
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
2525

2626
interface T3<T extends T3<T>> {
2727
x: T["x"];

‎tests/baselines/reference/limitDeepInstantiations.errors.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
tests/cases/compiler/limitDeepInstantiations.ts(3,35): error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
1+
tests/cases/compiler/limitDeepInstantiations.ts(4,9): error TS2589: Type instantiation is excessively deep and possibly infinite.
22
tests/cases/compiler/limitDeepInstantiations.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'.
33

44

55
==== tests/cases/compiler/limitDeepInstantiations.ts (2 errors) ====
66
// Repro from #14837
77

88
type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
9-
~~~~~~
10-
!!! error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
119
let f1: Foo<"true", {}>;
10+
~~~~~~~~~~~~~~~
11+
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
1212
let f2: Foo<"false", {}>;
1313
~~~~~~~
1414
!!! error TS2344: Type '"false"' does not satisfy the constraint '"true"'.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// @strict: true
2+
// @declaration: true
3+
4+
declare const c1: {
5+
get foo(): typeof c1.foo;
6+
}
7+
8+
declare const c2: {
9+
set foo(value: typeof c2.foo);
10+
}
11+
12+
declare const c3: {
13+
get foo(): string;
14+
set foo(value: typeof c3.foo);
15+
}
16+
17+
type T1 = {
18+
get foo(): T1["foo"];
19+
}
20+
21+
type T2 = {
22+
set foo(value: T2["foo"]);
23+
}
24+
25+
type T3 = {
26+
get foo(): string;
27+
set foo(value: T3["foo"]);
28+
}

0 commit comments

Comments
 (0)
Please sign in to comment.