Skip to content

Commit c5f92d4

Browse files
authored
support generic variant setter (microsoft#55030)
1 parent 23c9752 commit c5f92d4

File tree

5 files changed

+174
-3
lines changed

5 files changed

+174
-3
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19098,10 +19098,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1909819098

1909919099
function instantiateSymbol(symbol: Symbol, mapper: TypeMapper): Symbol {
1910019100
const links = getSymbolLinks(symbol);
19101+
// If the type of the symbol is already resolved, and if that type could not possibly
19102+
// be affected by instantiation, simply return the symbol itself.
1910119103
if (links.type && !couldContainTypeVariables(links.type)) {
19102-
// If the type of the symbol is already resolved, and if that type could not possibly
19103-
// be affected by instantiation, simply return the symbol itself.
19104-
return symbol;
19104+
if (!(symbol.flags & SymbolFlags.SetAccessor)) {
19105+
return symbol;
19106+
}
19107+
// If we're a setter, check writeType.
19108+
if (links.writeType && !couldContainTypeVariables(links.writeType)) {
19109+
return symbol;
19110+
}
1910519111
}
1910619112
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
1910719113
// If symbol being instantiated is itself a instantiation, fetch the original target and combine the
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [tests/cases/compiler/divergentAccessorsTypes7.ts] ////
2+
3+
//// [divergentAccessorsTypes7.ts]
4+
class Test<S> {
5+
constructor() {}
6+
7+
set value(value: string | ((item: S) => string)) {}
8+
9+
get value(): string {
10+
return null!;
11+
}
12+
13+
// -- Replacing the getter such that the getter/setter types match, removes the error:
14+
// get value(): string | ((item: S) => string) {
15+
// return null!;
16+
// }
17+
18+
// -- Or, replacing the setter such that a concrete type is used, removes the error:
19+
// set value(value: string | ((item: { property: string }) => string)) {}
20+
}
21+
22+
const a = new Test<{
23+
property: string
24+
}>();
25+
26+
a.value = (item) => item.property
27+
28+
29+
//// [divergentAccessorsTypes7.js]
30+
var Test = /** @class */ (function () {
31+
function Test() {
32+
}
33+
Object.defineProperty(Test.prototype, "value", {
34+
get: function () {
35+
return null;
36+
},
37+
set: function (value) { },
38+
enumerable: false,
39+
configurable: true
40+
});
41+
return Test;
42+
}());
43+
var a = new Test();
44+
a.value = function (item) { return item.property; };
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//// [tests/cases/compiler/divergentAccessorsTypes7.ts] ////
2+
3+
=== divergentAccessorsTypes7.ts ===
4+
class Test<S> {
5+
>Test : Symbol(Test, Decl(divergentAccessorsTypes7.ts, 0, 0))
6+
>S : Symbol(S, Decl(divergentAccessorsTypes7.ts, 0, 11))
7+
8+
constructor() {}
9+
10+
set value(value: string | ((item: S) => string)) {}
11+
>value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55))
12+
>value : Symbol(value, Decl(divergentAccessorsTypes7.ts, 3, 14))
13+
>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 3, 32))
14+
>S : Symbol(S, Decl(divergentAccessorsTypes7.ts, 0, 11))
15+
16+
get value(): string {
17+
>value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55))
18+
19+
return null!;
20+
}
21+
22+
// -- Replacing the getter such that the getter/setter types match, removes the error:
23+
// get value(): string | ((item: S) => string) {
24+
// return null!;
25+
// }
26+
27+
// -- Or, replacing the setter such that a concrete type is used, removes the error:
28+
// set value(value: string | ((item: { property: string }) => string)) {}
29+
}
30+
31+
const a = new Test<{
32+
>a : Symbol(a, Decl(divergentAccessorsTypes7.ts, 18, 5))
33+
>Test : Symbol(Test, Decl(divergentAccessorsTypes7.ts, 0, 0))
34+
35+
property: string
36+
>property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20))
37+
38+
}>();
39+
40+
a.value = (item) => item.property
41+
>a.value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55))
42+
>a : Symbol(a, Decl(divergentAccessorsTypes7.ts, 18, 5))
43+
>value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55))
44+
>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 22, 11))
45+
>item.property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20))
46+
>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 22, 11))
47+
>property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20))
48+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//// [tests/cases/compiler/divergentAccessorsTypes7.ts] ////
2+
3+
=== divergentAccessorsTypes7.ts ===
4+
class Test<S> {
5+
>Test : Test<S>
6+
7+
constructor() {}
8+
9+
set value(value: string | ((item: S) => string)) {}
10+
>value : string
11+
>value : string | ((item: S) => string)
12+
>item : S
13+
14+
get value(): string {
15+
>value : string
16+
17+
return null!;
18+
>null! : null
19+
}
20+
21+
// -- Replacing the getter such that the getter/setter types match, removes the error:
22+
// get value(): string | ((item: S) => string) {
23+
// return null!;
24+
// }
25+
26+
// -- Or, replacing the setter such that a concrete type is used, removes the error:
27+
// set value(value: string | ((item: { property: string }) => string)) {}
28+
}
29+
30+
const a = new Test<{
31+
>a : Test<{ property: string; }>
32+
>new Test<{ property: string}>() : Test<{ property: string; }>
33+
>Test : typeof Test
34+
35+
property: string
36+
>property : string
37+
38+
}>();
39+
40+
a.value = (item) => item.property
41+
>a.value = (item) => item.property : (item: { property: string; }) => string
42+
>a.value : string | ((item: { property: string; }) => string)
43+
>a : Test<{ property: string; }>
44+
>value : string | ((item: { property: string; }) => string)
45+
>(item) => item.property : (item: { property: string; }) => string
46+
>item : { property: string; }
47+
>item.property : string
48+
>item : { property: string; }
49+
>property : string
50+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Test<S> {
2+
constructor() {}
3+
4+
set value(value: string | ((item: S) => string)) {}
5+
6+
get value(): string {
7+
return null!;
8+
}
9+
10+
// -- Replacing the getter such that the getter/setter types match, removes the error:
11+
// get value(): string | ((item: S) => string) {
12+
// return null!;
13+
// }
14+
15+
// -- Or, replacing the setter such that a concrete type is used, removes the error:
16+
// set value(value: string | ((item: { property: string }) => string)) {}
17+
}
18+
19+
const a = new Test<{
20+
property: string
21+
}>();
22+
23+
a.value = (item) => item.property

0 commit comments

Comments
 (0)