Skip to content

Commit 919d86d

Browse files
ahejlsbergmprobst
authored andcommitted
Fix mapped type instantiation circularity (microsoft#46586)
* Don't obtain constraint if doing so would cause circularity * Add regression test * Address CR feedback
1 parent 3712d3e commit 919d86d

File tree

6 files changed

+77
-4
lines changed

6 files changed

+77
-4
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16604,7 +16604,8 @@ namespace ts {
1660416604
if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) {
1660516605
if (!type.declaration.nameType) {
1660616606
let constraint;
16607-
if (isArrayType(t) || (t.flags & TypeFlags.Any) && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, or(isArrayType, isTupleType))) {
16607+
if (isArrayType(t) || t.flags & TypeFlags.Any && findResolutionCycleStartIndex(typeVariable, TypeSystemPropertyName.ImmediateBaseConstraint) < 0 &&
16608+
(constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, or(isArrayType, isTupleType))) {
1660816609
return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper));
1660916610
}
1661016611
if (isGenericTupleType(t)) {

tests/baselines/reference/mappedTypeWithAny.errors.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,14 @@ tests/cases/conformance/types/mapped/mappedTypeWithAny.ts(53,5): error TS2322: T
6767
let def: [any, any] = stringifyPair(void 0 as any);
6868
~~~
6969
!!! error TS2322: Type 'string[]' is not assignable to type '[any, any]'.
70-
!!! error TS2322: Target requires 2 element(s) but source may have fewer.
70+
!!! error TS2322: Target requires 2 element(s) but source may have fewer.
71+
72+
// Repro from #46582
73+
74+
type Evolvable<E extends Evolver> = {
75+
[P in keyof E]: never;
76+
};
77+
type Evolver<T extends Evolvable<any> = any> = {
78+
[key in keyof Partial<T>]: never;
79+
};
80+

tests/baselines/reference/mappedTypeWithAny.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,17 @@ declare function stringifyArray<T extends readonly any[]>(arr: T): { -readonly [
5151
let abc: any[] = stringifyArray(void 0 as any);
5252

5353
declare function stringifyPair<T extends readonly [any, any]>(arr: T): { -readonly [K in keyof T]: string };
54-
let def: [any, any] = stringifyPair(void 0 as any);
54+
let def: [any, any] = stringifyPair(void 0 as any);
55+
56+
// Repro from #46582
57+
58+
type Evolvable<E extends Evolver> = {
59+
[P in keyof E]: never;
60+
};
61+
type Evolver<T extends Evolvable<any> = any> = {
62+
[key in keyof Partial<T>]: never;
63+
};
64+
5565

5666
//// [mappedTypeWithAny.js]
5767
"use strict";
@@ -110,3 +120,9 @@ declare function stringifyPair<T extends readonly [any, any]>(arr: T): {
110120
-readonly [K in keyof T]: string;
111121
};
112122
declare let def: [any, any];
123+
declare type Evolvable<E extends Evolver> = {
124+
[P in keyof E]: never;
125+
};
126+
declare type Evolver<T extends Evolvable<any> = any> = {
127+
[key in keyof Partial<T>]: never;
128+
};

tests/baselines/reference/mappedTypeWithAny.symbols

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,27 @@ let def: [any, any] = stringifyPair(void 0 as any);
151151
>def : Symbol(def, Decl(mappedTypeWithAny.ts, 52, 3))
152152
>stringifyPair : Symbol(stringifyPair, Decl(mappedTypeWithAny.ts, 49, 47))
153153

154+
// Repro from #46582
155+
156+
type Evolvable<E extends Evolver> = {
157+
>Evolvable : Symbol(Evolvable, Decl(mappedTypeWithAny.ts, 52, 51))
158+
>E : Symbol(E, Decl(mappedTypeWithAny.ts, 56, 15))
159+
>Evolver : Symbol(Evolver, Decl(mappedTypeWithAny.ts, 58, 2))
160+
161+
[P in keyof E]: never;
162+
>P : Symbol(P, Decl(mappedTypeWithAny.ts, 57, 3))
163+
>E : Symbol(E, Decl(mappedTypeWithAny.ts, 56, 15))
164+
165+
};
166+
type Evolver<T extends Evolvable<any> = any> = {
167+
>Evolver : Symbol(Evolver, Decl(mappedTypeWithAny.ts, 58, 2))
168+
>T : Symbol(T, Decl(mappedTypeWithAny.ts, 59, 13))
169+
>Evolvable : Symbol(Evolvable, Decl(mappedTypeWithAny.ts, 52, 51))
170+
171+
[key in keyof Partial<T>]: never;
172+
>key : Symbol(key, Decl(mappedTypeWithAny.ts, 60, 3))
173+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
174+
>T : Symbol(T, Decl(mappedTypeWithAny.ts, 59, 13))
175+
176+
};
177+

tests/baselines/reference/mappedTypeWithAny.types

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,16 @@ let def: [any, any] = stringifyPair(void 0 as any);
125125
>void 0 : undefined
126126
>0 : 0
127127

128+
// Repro from #46582
129+
130+
type Evolvable<E extends Evolver> = {
131+
>Evolvable : Evolvable<E>
132+
133+
[P in keyof E]: never;
134+
};
135+
type Evolver<T extends Evolvable<any> = any> = {
136+
>Evolver : Evolver<T>
137+
138+
[key in keyof Partial<T>]: never;
139+
};
140+

tests/cases/conformance/types/mapped/mappedTypeWithAny.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,13 @@ declare function stringifyArray<T extends readonly any[]>(arr: T): { -readonly [
5353
let abc: any[] = stringifyArray(void 0 as any);
5454

5555
declare function stringifyPair<T extends readonly [any, any]>(arr: T): { -readonly [K in keyof T]: string };
56-
let def: [any, any] = stringifyPair(void 0 as any);
56+
let def: [any, any] = stringifyPair(void 0 as any);
57+
58+
// Repro from #46582
59+
60+
type Evolvable<E extends Evolver> = {
61+
[P in keyof E]: never;
62+
};
63+
type Evolver<T extends Evolvable<any> = any> = {
64+
[key in keyof Partial<T>]: never;
65+
};

0 commit comments

Comments
 (0)