Skip to content

Conversation

@thromel
Copy link

@thromel thromel commented Dec 28, 2025

Fixes #62779

Problem

When object literal methods reference this inside a function with a reverse mapped type parameter, the type parameter T was leaking through:

declare function test<T extends Record<string, unknown>>(obj: {
    [K in keyof T]: () => T[K];
}): T;

const obj = test({
    a() { return 0; },
    b() { return this.a(); },
});
// Expected: { a: number; b: number; }
// Actual:   { a: number; b: T[string]; } (widened to unknown)

Cause

In getContextualThisParameterType, when computing the this type for method b, the code was using the contextual type (the mapped type { [K in keyof T]: () => T[K] }) with unresolved type parameters. This caused this.a() to be typed as T["a"] rather than the already-inferred number.

Solution

When in an inference context, use the actual object literal type via checkExpressionCached(containingLiteral) rather than the contextual mapped type. This allows methods to see each other's already-inferred types when resolving this references.

Test Plan

  • Added test case reverseMappedThisTypeInference.ts demonstrating the fix
  • Verified all existing contextual, inference, and reverse mapped type tests pass

@github-project-automation github-project-automation bot moved this to Not started in PR Backlog Dec 28, 2025
@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Dec 28, 2025
Fixes microsoft#62779

When object literal methods reference `this` inside a function with a
reverse mapped type parameter, the type parameter T was leaking through.
For example:

```typescript
declare function test<T extends Record<string, unknown>>(obj: {
    [K in keyof T]: () => T[K];
}): T;

const obj = test({
    a() { return 0; },
    b() { return this.a(); },
});
// Was: { a: number; b: T[string]; } (widened to unknown)
// Now: { a: number; b: number; }
```

The fix modifies `getContextualThisParameterType` to use the actual
object literal type when in an inference context with a mapped type
contextual type (like reverse mapped types). This allows methods to
see each other's already-inferred types when resolving `this` references,
rather than using the uninstantiated mapped type with type variables.
@thromel thromel force-pushed the fix/reverse-mapped-this-type-leak branch from 602ed22 to 7155d8f Compare December 28, 2025 06:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

Type parameter leak caused by this and reverse mapped type

2 participants