From c5f92d4150f465381f2f22e783907eaaa9df5122 Mon Sep 17 00:00:00 2001 From: Zzzen Date: Wed, 30 Aug 2023 05:11:33 +0800 Subject: [PATCH] support generic variant setter (#55030) --- src/compiler/checker.ts | 12 +++-- .../reference/divergentAccessorsTypes7.js | 44 ++++++++++++++++ .../divergentAccessorsTypes7.symbols | 48 ++++++++++++++++++ .../reference/divergentAccessorsTypes7.types | 50 +++++++++++++++++++ .../compiler/divergentAccessorsTypes7.ts | 23 +++++++++ 5 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/divergentAccessorsTypes7.js create mode 100644 tests/baselines/reference/divergentAccessorsTypes7.symbols create mode 100644 tests/baselines/reference/divergentAccessorsTypes7.types create mode 100644 tests/cases/compiler/divergentAccessorsTypes7.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 46dafbdae9d..8e49e18d4d1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19098,10 +19098,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function instantiateSymbol(symbol: Symbol, mapper: TypeMapper): Symbol { const links = getSymbolLinks(symbol); + // If the type of the symbol is already resolved, and if that type could not possibly + // be affected by instantiation, simply return the symbol itself. if (links.type && !couldContainTypeVariables(links.type)) { - // If the type of the symbol is already resolved, and if that type could not possibly - // be affected by instantiation, simply return the symbol itself. - return symbol; + if (!(symbol.flags & SymbolFlags.SetAccessor)) { + return symbol; + } + // If we're a setter, check writeType. + if (links.writeType && !couldContainTypeVariables(links.writeType)) { + return symbol; + } } if (getCheckFlags(symbol) & CheckFlags.Instantiated) { // If symbol being instantiated is itself a instantiation, fetch the original target and combine the diff --git a/tests/baselines/reference/divergentAccessorsTypes7.js b/tests/baselines/reference/divergentAccessorsTypes7.js new file mode 100644 index 00000000000..ed5cdb501d1 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes7.js @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/divergentAccessorsTypes7.ts] //// + +//// [divergentAccessorsTypes7.ts] +class Test { + constructor() {} + + set value(value: string | ((item: S) => string)) {} + + get value(): string { + return null!; + } + + // -- Replacing the getter such that the getter/setter types match, removes the error: + // get value(): string | ((item: S) => string) { + // return null!; + // } + + // -- Or, replacing the setter such that a concrete type is used, removes the error: + // set value(value: string | ((item: { property: string }) => string)) {} +} + +const a = new Test<{ + property: string +}>(); + +a.value = (item) => item.property + + +//// [divergentAccessorsTypes7.js] +var Test = /** @class */ (function () { + function Test() { + } + Object.defineProperty(Test.prototype, "value", { + get: function () { + return null; + }, + set: function (value) { }, + enumerable: false, + configurable: true + }); + return Test; +}()); +var a = new Test(); +a.value = function (item) { return item.property; }; diff --git a/tests/baselines/reference/divergentAccessorsTypes7.symbols b/tests/baselines/reference/divergentAccessorsTypes7.symbols new file mode 100644 index 00000000000..ea856545779 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes7.symbols @@ -0,0 +1,48 @@ +//// [tests/cases/compiler/divergentAccessorsTypes7.ts] //// + +=== divergentAccessorsTypes7.ts === +class Test { +>Test : Symbol(Test, Decl(divergentAccessorsTypes7.ts, 0, 0)) +>S : Symbol(S, Decl(divergentAccessorsTypes7.ts, 0, 11)) + + constructor() {} + + set value(value: string | ((item: S) => string)) {} +>value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55)) +>value : Symbol(value, Decl(divergentAccessorsTypes7.ts, 3, 14)) +>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 3, 32)) +>S : Symbol(S, Decl(divergentAccessorsTypes7.ts, 0, 11)) + + get value(): string { +>value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55)) + + return null!; + } + + // -- Replacing the getter such that the getter/setter types match, removes the error: + // get value(): string | ((item: S) => string) { + // return null!; + // } + + // -- Or, replacing the setter such that a concrete type is used, removes the error: + // set value(value: string | ((item: { property: string }) => string)) {} +} + +const a = new Test<{ +>a : Symbol(a, Decl(divergentAccessorsTypes7.ts, 18, 5)) +>Test : Symbol(Test, Decl(divergentAccessorsTypes7.ts, 0, 0)) + + property: string +>property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20)) + +}>(); + +a.value = (item) => item.property +>a.value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55)) +>a : Symbol(a, Decl(divergentAccessorsTypes7.ts, 18, 5)) +>value : Symbol(Test.value, Decl(divergentAccessorsTypes7.ts, 1, 20), Decl(divergentAccessorsTypes7.ts, 3, 55)) +>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 22, 11)) +>item.property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20)) +>item : Symbol(item, Decl(divergentAccessorsTypes7.ts, 22, 11)) +>property : Symbol(property, Decl(divergentAccessorsTypes7.ts, 18, 20)) + diff --git a/tests/baselines/reference/divergentAccessorsTypes7.types b/tests/baselines/reference/divergentAccessorsTypes7.types new file mode 100644 index 00000000000..95e494f4d3d --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes7.types @@ -0,0 +1,50 @@ +//// [tests/cases/compiler/divergentAccessorsTypes7.ts] //// + +=== divergentAccessorsTypes7.ts === +class Test { +>Test : Test + + constructor() {} + + set value(value: string | ((item: S) => string)) {} +>value : string +>value : string | ((item: S) => string) +>item : S + + get value(): string { +>value : string + + return null!; +>null! : null + } + + // -- Replacing the getter such that the getter/setter types match, removes the error: + // get value(): string | ((item: S) => string) { + // return null!; + // } + + // -- Or, replacing the setter such that a concrete type is used, removes the error: + // set value(value: string | ((item: { property: string }) => string)) {} +} + +const a = new Test<{ +>a : Test<{ property: string; }> +>new Test<{ property: string}>() : Test<{ property: string; }> +>Test : typeof Test + + property: string +>property : string + +}>(); + +a.value = (item) => item.property +>a.value = (item) => item.property : (item: { property: string; }) => string +>a.value : string | ((item: { property: string; }) => string) +>a : Test<{ property: string; }> +>value : string | ((item: { property: string; }) => string) +>(item) => item.property : (item: { property: string; }) => string +>item : { property: string; } +>item.property : string +>item : { property: string; } +>property : string + diff --git a/tests/cases/compiler/divergentAccessorsTypes7.ts b/tests/cases/compiler/divergentAccessorsTypes7.ts new file mode 100644 index 00000000000..83082022105 --- /dev/null +++ b/tests/cases/compiler/divergentAccessorsTypes7.ts @@ -0,0 +1,23 @@ +class Test { + constructor() {} + + set value(value: string | ((item: S) => string)) {} + + get value(): string { + return null!; + } + + // -- Replacing the getter such that the getter/setter types match, removes the error: + // get value(): string | ((item: S) => string) { + // return null!; + // } + + // -- Or, replacing the setter such that a concrete type is used, removes the error: + // set value(value: string | ((item: { property: string }) => string)) {} +} + +const a = new Test<{ + property: string +}>(); + +a.value = (item) => item.property