Skip to content

Fix this type in object literal methods returned from async functions - #64962

Open
Harsh Vardhan Chauhan (1-DARK) wants to merge 1 commit into
microsoft:mainfrom
1-DARK:fix-async-return-this-type
Open

Harsh Vardhan Chauhan (1-DARK) wants to merge 1 commit into
microsoft:mainfrom
1-DARK:fix-async-return-this-type

Conversation

@1-DARK

Copy link
Copy Markdown

Fixes #64954

In an async function, the contextual type of a returned expression is T | PromiseLike<T>. getContextualThisParameterType used that whole union as this for methods in a returned object literal. So this was {…} | PromiseLike<{…}> instead of the object type, and this satisfies { … } failed with TS1360.

This only happened when the return type came from context, such as an annotated variable or an async callback. The unannotated form infers the literal's own type, so it was already correct.

const test2: () => Promise<{ value: number; method(): void }> = async () => {
  return {
    value: 5,
    method() {
      this satisfies { value: number; method(): void }; // error TS1360 before this fix
    },
  };
};

Fix

When the containing object literal is directly returned from an async, non-generator function, drop the synthesized PromiseLike<U> from the contextual type before deriving this.

  • This covers a return statement or an arrow body.
  • It only removes a PromiseLike<U> whose U is also a member of the same union.
  • A PromiseLike that isn't tied to a sibling member is left alone.

Verification

Case Original With fix
Callback: foo(async () => ({…})) error OK
Callback with a block body and return error OK
async function expression callback error OK
Declared async function f(): Promise<X> error OK
Nested literal ({ inner: {…} }) OK OK
Array element (Promise<X[]>) OK OK

The full go test ./... suite passes with no baseline changes.

Notes

  • A regression test (asyncReturnObjectLiteralThisType.ts, plus baselines) was written but isn't part of this PR.
  • Upstream TypeScript has the same behaviour and would need a separate patch.

Copilot AI balanced review requested due to automatic review settings October 25, 2026 19:35
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Oct 25, 2026
@typescript-automation typescript-automation Bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Oct 25, 2026
The contextual type of an async return expression is T | PromiseLike<T>.
Exclude the synthesized PromiseLike<T> when deriving 'this'.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The filter mishandles returned thenables and union-valued awaited types, and regression tests are not included.

3 open issues
What changed in this PR

This PR addresses #64954 by adjusting contextual this typing for object-literal methods returned directly from async functions in the native TypeScript compiler.

Changes:

  • Filters matching synthesized PromiseLike<T> members before deriving this.
  • Adds detection for direct async returns, including parenthesized expressions and concise arrow bodies, while excluding generators.
File Description
tsc/​internal/​checker/​checker.go Adds async-return detection and contextual this filtering.

Review effort: Balanced

Comment on lines +12291 to +12292
if contextualType.flags&TypeFlagsUnion != 0 && c.isAsyncReturnExpression(containingLiteral) {
// The contextual type of an async return expression is `T | PromiseLike<T>`; `this` is just `T`.
Comment on lines +12300 to +12301
args := c.getTypeArguments(t)
return len(args) != 1 || !slices.Contains(members, args[0])
// for 'this' is the non-null form of the contextual type for the containing object literal or
// the type of the object literal itself.
if contextualType != nil {
if contextualType.flags&TypeFlagsUnion != 0 && c.isAsyncReturnExpression(containingLiteral) {

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

Type annotations cause contextual this in object literal returned from an async function to be inferred as Promise<This> | This

2 participants