Skip to content

Support promise-like types in contextual return type of async function#27256

Closed
rbuckton wants to merge 3 commits intorelease-3.1from
fix24629
Closed

Support promise-like types in contextual return type of async function#27256
rbuckton wants to merge 3 commits intorelease-3.1from
fix24629

Conversation

@rbuckton
Copy link
Copy Markdown
Contributor

@rbuckton rbuckton commented Sep 21, 2018

This changes the contextual type we use for a return expression in an async function. Prior to this change, we would infer {} for the type argument to Promise below:

interface Obj { key: "value"; }

function fn1(): Promise<Obj> {
    // ok: return expression is contextually typed to 'Promise<Obj>' so 'T' in 'Promise<T>' 
    // is contextually typed to 'Obj'.
    return new Promise(resolve => { resolve({ key: "value" }); });
}

async function fn2(): Promise<Obj> {
    // ok: return expression is contextually typed to 'Obj'.
    return { key: "value" }; 
}

async function fn3(): Promise<Obj> {
    // error: '{}' is not assignable to type 'Obj'.
    // return expression is contextually typed to 'Obj' so 'T' in 'Promise<T>' is not
    // contextually typed and becomes '{}'
    return new Promise(resolve => { resolve({ key: "value" }); });
}

This is because we use the "awaited type" Obj for the return type Promise<Obj> as the contextual type. With this change, we use Obj | PromiseLike<Obj> as the contextual type:

interface Obj { key: "value"; }

function fn1(): Promise<Obj> {
    // ok: return expression is contextually typed to 'Promise<Obj>' so 'T' in 'Promise<T>' 
    // is contextually typed to 'Obj'.
    return new Promise(resolve => { resolve({ key: "value" }); });
}

async function fn2(): Promise<Obj> {
    // ok: return expression is contextually typed to 'Obj | PromiseLike<Obj>'.
    return { key: "value" }; 
}

async function fn3(): Promise<Obj> {
    // ok: return expression is contextually typed to 'Obj | PromiseLike<Obj>' so 'T' in 
    // 'Promise<T>' is contextually typed to 'Obj'
    return new Promise(resolve => { resolve({ key: "value" }); });
}

Fixes #24629, #27001

@rbuckton
Copy link
Copy Markdown
Contributor Author

@weswigham: I opted to just continue using PromiseLike as opposed to some other construct for the time being.

@DanielRosenwasser
Copy link
Copy Markdown
Member

Does this fix #27001 too?

@rbuckton
Copy link
Copy Markdown
Contributor Author

@DanielRosenwasser: I don't think it does, but I will check that tomorrow.

@rbuckton
Copy link
Copy Markdown
Contributor Author

@DanielRosenwasser: It does now, the fix for #27001 was easy to accomplish with the changes in this PR since you need the same behavior (union the awaited type with a PromiseLike of the awaited type).

@rbuckton
Copy link
Copy Markdown
Contributor Author

This change is postponed to 3.2, you can find the PR against master here: #27270

@rbuckton rbuckton closed this Sep 21, 2018
@rbuckton rbuckton deleted the fix24629 branch September 21, 2018 17:46
@microsoft microsoft locked as resolved and limited conversation to collaborators Oct 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants