diff --git a/tests/baselines/reference/reverseMappedThisLeak.errors.txt b/tests/baselines/reference/reverseMappedThisLeak.errors.txt new file mode 100644 index 0000000000000..cd9c26f7eafb5 --- /dev/null +++ b/tests/baselines/reference/reverseMappedThisLeak.errors.txt @@ -0,0 +1,24 @@ +reverseMappedThisLeak.ts(16,5): error TS2349: This expression is not callable. + Type 'unknown' has no call signatures. + + +==== reverseMappedThisLeak.ts (1 errors) ==== + declare function test>(obj:{ + [K in keyof T]: () => T[K]; + }): T; + + const obj = test({ + a() { + return 1; + }, + b() { + return this.a(); + // Expected: number + // Actual: T[string] (bug) + } + }); + + obj.b(); // should be `number`, but currently inferred as `T[string]` + ~ +!!! error TS2349: This expression is not callable. +!!! error TS2349: Type 'unknown' has no call signatures. \ No newline at end of file diff --git a/tests/baselines/reference/reverseMappedThisLeak.js b/tests/baselines/reference/reverseMappedThisLeak.js new file mode 100644 index 0000000000000..cb76ff31b3d82 --- /dev/null +++ b/tests/baselines/reference/reverseMappedThisLeak.js @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/reverseMappedThisLeak.ts] //// + +//// [reverseMappedThisLeak.ts] +declare function test>(obj:{ + [K in keyof T]: () => T[K]; +}): T; + +const obj = test({ + a() { + return 1; + }, + b() { + return this.a(); + // Expected: number + // Actual: T[string] (bug) + } +}); + +obj.b(); // should be `number`, but currently inferred as `T[string]` + +//// [reverseMappedThisLeak.js] +"use strict"; +var obj = test({ + a: function () { + return 1; + }, + b: function () { + return this.a(); + // Expected: number + // Actual: T[string] (bug) + } +}); +obj.b(); // should be `number`, but currently inferred as `T[string]` diff --git a/tests/baselines/reference/reverseMappedThisLeak.symbols b/tests/baselines/reference/reverseMappedThisLeak.symbols new file mode 100644 index 0000000000000..cba7f49f4750f --- /dev/null +++ b/tests/baselines/reference/reverseMappedThisLeak.symbols @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/reverseMappedThisLeak.ts] //// + +=== reverseMappedThisLeak.ts === +declare function test>(obj:{ +>test : Symbol(test, Decl(reverseMappedThisLeak.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedThisLeak.ts, 0, 22)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(reverseMappedThisLeak.ts, 0, 57)) + + [K in keyof T]: () => T[K]; +>K : Symbol(K, Decl(reverseMappedThisLeak.ts, 1, 3)) +>T : Symbol(T, Decl(reverseMappedThisLeak.ts, 0, 22)) +>T : Symbol(T, Decl(reverseMappedThisLeak.ts, 0, 22)) +>K : Symbol(K, Decl(reverseMappedThisLeak.ts, 1, 3)) + +}): T; +>T : Symbol(T, Decl(reverseMappedThisLeak.ts, 0, 22)) + +const obj = test({ +>obj : Symbol(obj, Decl(reverseMappedThisLeak.ts, 4, 5)) +>test : Symbol(test, Decl(reverseMappedThisLeak.ts, 0, 0)) + + a() { +>a : Symbol(a, Decl(reverseMappedThisLeak.ts, 4, 18)) + + return 1; + }, + b() { +>b : Symbol(b, Decl(reverseMappedThisLeak.ts, 7, 4)) + + return this.a(); +>this.a : Symbol(a, Decl(reverseMappedThisLeak.ts, 4, 18)) +>this : Symbol(__type, Decl(reverseMappedThisLeak.ts, 0, 61)) +>a : Symbol(a, Decl(reverseMappedThisLeak.ts, 4, 18)) + + // Expected: number + // Actual: T[string] (bug) + } +}); + +obj.b(); // should be `number`, but currently inferred as `T[string]` +>obj.b : Symbol(b, Decl(reverseMappedThisLeak.ts, 7, 4)) +>obj : Symbol(obj, Decl(reverseMappedThisLeak.ts, 4, 5)) +>b : Symbol(b, Decl(reverseMappedThisLeak.ts, 7, 4)) + diff --git a/tests/baselines/reference/reverseMappedThisLeak.types b/tests/baselines/reference/reverseMappedThisLeak.types new file mode 100644 index 0000000000000..d4a66dcdc3bb3 --- /dev/null +++ b/tests/baselines/reference/reverseMappedThisLeak.types @@ -0,0 +1,60 @@ +//// [tests/cases/compiler/reverseMappedThisLeak.ts] //// + +=== reverseMappedThisLeak.ts === +declare function test>(obj:{ +>test : >(obj: { [K in keyof T]: () => T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>obj : { [K in keyof T]: () => T[K]; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^ + + [K in keyof T]: () => T[K]; +}): T; + +const obj = test({ +>obj : { a: number; b: T[string]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>test({ a() { return 1; }, b() { return this.a(); // Expected: number // Actual: T[string] (bug) }}) : { a: number; b: T[string]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>test : >(obj: { [K in keyof T]: () => T[K]; }) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ a() { return 1; }, b() { return this.a(); // Expected: number // Actual: T[string] (bug) }} : { a(): number; b(): T[string]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + a() { +>a : () => number +> : ^^^^^^^^^^^^ + + return 1; +>1 : 1 +> : ^ + + }, + b() { +>b : () => T[string] +> : ^^^^^^^^^^^^^^^ + + return this.a(); +>this.a() : number +> : ^^^^^^ +>this.a : () => number +> : ^^^^^^^^^^^^ +>this : { a: () => number; b: () => T[string]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>a : () => number +> : ^^^^^^^^^^^^ + + // Expected: number + // Actual: T[string] (bug) + } +}); + +obj.b(); // should be `number`, but currently inferred as `T[string]` +>obj.b() : any +> : ^^^ +>obj.b : T[string] +> : ^^^^^^^^^ +>obj : { a: number; b: T[string]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>b : T[string] +> : ^^^^^^^^^ + diff --git a/tests/cases/compiler/reverseMappedThisLeak.ts b/tests/cases/compiler/reverseMappedThisLeak.ts new file mode 100644 index 0000000000000..6010006b2100a --- /dev/null +++ b/tests/cases/compiler/reverseMappedThisLeak.ts @@ -0,0 +1,18 @@ +// @strict: true + +declare function test>(obj:{ + [K in keyof T]: () => T[K]; +}): T; + +const obj = test({ + a() { + return 1; + }, + b() { + return this.a(); + // Expected: number + // Actual: T[string] (bug) + } +}); + +obj.b(); // should be `number`, but currently inferred as `T[string]` \ No newline at end of file