Skip to content

Commit 9816f15

Browse files
ahejlsbergtypescript-bot
authored andcommitted
Cherry-pick PR microsoft#38653 into release-3.9
Component commits: 97cb818 No contextual types from circular mapped type properties 1dcf4ab Add regression test
1 parent a076e9e commit 9816f15

File tree

5 files changed

+158
-1
lines changed

5 files changed

+158
-1
lines changed

src/compiler/checker.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -22384,6 +22384,10 @@ namespace ts {
2238422384
}
2238522385
}
2238622386

22387+
function isCircularMappedProperty(symbol: Symbol) {
22388+
return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(<MappedSymbol>symbol).type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0);
22389+
}
22390+
2238722391
function getTypeOfPropertyOfContextualType(type: Type, name: __String) {
2238822392
return mapType(type, t => {
2238922393
if (isGenericMappedType(t)) {
@@ -22397,7 +22401,7 @@ namespace ts {
2239722401
else if (t.flags & TypeFlags.StructuredType) {
2239822402
const prop = getPropertyOfType(t, name);
2239922403
if (prop) {
22400-
return getTypeOfSymbol(prop);
22404+
return isCircularMappedProperty(prop) ? undefined : getTypeOfSymbol(prop);
2240122405
}
2240222406
if (isTupleType(t)) {
2240322407
const restType = getRestTypeOfTupleType(t);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [circularContextualMappedType.ts]
2+
type Func<T> = () => T;
3+
4+
type Mapped<T> = { [K in keyof T]: Func<T[K]> };
5+
6+
declare function reproduce(options: number): void;
7+
declare function reproduce<T>(options: Mapped<T>): T
8+
9+
reproduce({
10+
name: () => { return 123 }
11+
});
12+
13+
reproduce({
14+
name() { return 123 }
15+
});
16+
17+
reproduce({
18+
name: function () { return 123 }
19+
});
20+
21+
22+
//// [circularContextualMappedType.js]
23+
"use strict";
24+
reproduce({
25+
name: function () { return 123; }
26+
});
27+
reproduce({
28+
name: function () { return 123; }
29+
});
30+
reproduce({
31+
name: function () { return 123; }
32+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
=== tests/cases/compiler/circularContextualMappedType.ts ===
2+
type Func<T> = () => T;
3+
>Func : Symbol(Func, Decl(circularContextualMappedType.ts, 0, 0))
4+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 0, 10))
5+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 0, 10))
6+
7+
type Mapped<T> = { [K in keyof T]: Func<T[K]> };
8+
>Mapped : Symbol(Mapped, Decl(circularContextualMappedType.ts, 0, 23))
9+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 2, 12))
10+
>K : Symbol(K, Decl(circularContextualMappedType.ts, 2, 20))
11+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 2, 12))
12+
>Func : Symbol(Func, Decl(circularContextualMappedType.ts, 0, 0))
13+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 2, 12))
14+
>K : Symbol(K, Decl(circularContextualMappedType.ts, 2, 20))
15+
16+
declare function reproduce(options: number): void;
17+
>reproduce : Symbol(reproduce, Decl(circularContextualMappedType.ts, 2, 48), Decl(circularContextualMappedType.ts, 4, 50))
18+
>options : Symbol(options, Decl(circularContextualMappedType.ts, 4, 27))
19+
20+
declare function reproduce<T>(options: Mapped<T>): T
21+
>reproduce : Symbol(reproduce, Decl(circularContextualMappedType.ts, 2, 48), Decl(circularContextualMappedType.ts, 4, 50))
22+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 5, 27))
23+
>options : Symbol(options, Decl(circularContextualMappedType.ts, 5, 30))
24+
>Mapped : Symbol(Mapped, Decl(circularContextualMappedType.ts, 0, 23))
25+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 5, 27))
26+
>T : Symbol(T, Decl(circularContextualMappedType.ts, 5, 27))
27+
28+
reproduce({
29+
>reproduce : Symbol(reproduce, Decl(circularContextualMappedType.ts, 2, 48), Decl(circularContextualMappedType.ts, 4, 50))
30+
31+
name: () => { return 123 }
32+
>name : Symbol(name, Decl(circularContextualMappedType.ts, 7, 11))
33+
34+
});
35+
36+
reproduce({
37+
>reproduce : Symbol(reproduce, Decl(circularContextualMappedType.ts, 2, 48), Decl(circularContextualMappedType.ts, 4, 50))
38+
39+
name() { return 123 }
40+
>name : Symbol(name, Decl(circularContextualMappedType.ts, 11, 11))
41+
42+
});
43+
44+
reproduce({
45+
>reproduce : Symbol(reproduce, Decl(circularContextualMappedType.ts, 2, 48), Decl(circularContextualMappedType.ts, 4, 50))
46+
47+
name: function () { return 123 }
48+
>name : Symbol(name, Decl(circularContextualMappedType.ts, 15, 11))
49+
50+
});
51+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
=== tests/cases/compiler/circularContextualMappedType.ts ===
2+
type Func<T> = () => T;
3+
>Func : Func<T>
4+
5+
type Mapped<T> = { [K in keyof T]: Func<T[K]> };
6+
>Mapped : Mapped<T>
7+
8+
declare function reproduce(options: number): void;
9+
>reproduce : { (options: number): void; <T>(options: Mapped<T>): T; }
10+
>options : number
11+
12+
declare function reproduce<T>(options: Mapped<T>): T
13+
>reproduce : { (options: number): void; <T>(options: Mapped<T>): T; }
14+
>options : Mapped<T>
15+
16+
reproduce({
17+
>reproduce({ name: () => { return 123 }}) : { name: number; }
18+
>reproduce : { (options: number): void; <T>(options: Mapped<T>): T; }
19+
>{ name: () => { return 123 }} : { name: () => number; }
20+
21+
name: () => { return 123 }
22+
>name : () => number
23+
>() => { return 123 } : () => number
24+
>123 : 123
25+
26+
});
27+
28+
reproduce({
29+
>reproduce({ name() { return 123 }}) : { name: number; }
30+
>reproduce : { (options: number): void; <T>(options: Mapped<T>): T; }
31+
>{ name() { return 123 }} : { name(): number; }
32+
33+
name() { return 123 }
34+
>name : () => number
35+
>123 : 123
36+
37+
});
38+
39+
reproduce({
40+
>reproduce({ name: function () { return 123 }}) : { name: number; }
41+
>reproduce : { (options: number): void; <T>(options: Mapped<T>): T; }
42+
>{ name: function () { return 123 }} : { name: () => number; }
43+
44+
name: function () { return 123 }
45+
>name : () => number
46+
>function () { return 123 } : () => number
47+
>123 : 123
48+
49+
});
50+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @strict: true
2+
3+
type Func<T> = () => T;
4+
5+
type Mapped<T> = { [K in keyof T]: Func<T[K]> };
6+
7+
declare function reproduce(options: number): void;
8+
declare function reproduce<T>(options: Mapped<T>): T
9+
10+
reproduce({
11+
name: () => { return 123 }
12+
});
13+
14+
reproduce({
15+
name() { return 123 }
16+
});
17+
18+
reproduce({
19+
name: function () { return 123 }
20+
});

0 commit comments

Comments
 (0)