Skip to content

TS80007: Async function response arguments not inferred #32571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Rjpdude opened this issue Jul 26, 2019 · 6 comments
Closed

TS80007: Async function response arguments not inferred #32571

Rjpdude opened this issue Jul 26, 2019 · 6 comments
Assignees
Labels
Bug A bug in TypeScript Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@Rjpdude
Copy link

Rjpdude commented Jul 26, 2019

TypeScript Version: [email protected]

Search Terms: TS80007 as of #32384

Code

type MaybePromise<T> = T | Promise<T>

type StatefulModifier<S> = MaybePromise<(arg: S) => number>

type CountActions<S = { count: number }> = Record<string, 
    (...args: any[]) => StatefulModifier<S>
>

const actions: CountActions = {
    // works fine, `state` arg correctly inferred
    increment: (toAdd: number) => {
        return (state) => state.count + toAdd
    },

    // works fine, `state` arg correctly inferred from a promise.resolve res
    first: () => Promise.resolve(mockedPromise()).then((res) => {
        return (state) => state.count + res
    }),

    // works fine, `state` arg correctly inferred from a new promise
    second: () => new Promise((res) => {
        res((state) => state.count + 50)
    }),

    // fails, `state` arg as `any` and TS warning 80007 on async
    third: async () => {
        const res = await mockedPromise()

        // arg type inferred as any
        return (arg) => {
            return 10 * res
        }
    },
}

Expected behavior:

The promised function signature of the third object property should be inferred in the same respect as the previous two promised functions.

Actual behavior:

Typescript is able to infer the promised function signature when it's provided through => Promise.resolve or => new Promise(... but unable to do so when supplied as a result of an async function.

However, the inference resolves correctly when the MaybePromise union type is just simply a promise:

type MaybePromise<T> = Promise<T>

Playground Link: Click me

@RyanCavanaugh
Copy link
Member

I think we need to update the contextual typing rules for async functions to include the case where the contextual type is a union where one or more constituents is a Promise type

Simplified

type MaybePromise<T> = T | Promise<T>;
type NumberToNumber = (arg: number) => number;
type CountActions = Record<string,  () => MaybePromise<NumberToNumber>>;

const actions: CountActions = {
    // OK
    increment: () => (state) => state,

    // OK
    first: () => Promise.resolve(mockedPromise()).then((res) => 
        (state) => state + res
    ),

    // OK
    second: () => new Promise((res) => {
        res((state) => state)
    }),

    // fails, arg is `any`
    third: async () => {
        return (arg) => {
            return 10
        }
    },
}

const mockedPromise = () => new Promise<number>(res => {
    setTimeout(() => res(10), 1200)
})

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Jul 31, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.7.0 milestone Jul 31, 2019
@fab1o
Copy link

fab1o commented Oct 1, 2019

I have a bug to report, I'll leave this here because it seems related but I'm not sure if it's TypeScript or VSCode responsiblity, since this is just JavaScript in VSCode using JSDocs/ESDocs. But I guess VSCode uses TypeScript to infer types? Please let me know if I should report this in VSCode instead.

x is inferred with any instead of null:

 /**
  * @returns {Promise<null>} 
  */
 async method(listener) { }

 var x = await method(); // x is 'any' but it should be null

It only fails for null or undefined. It works for other types.

@Ethan-Arrowood
Copy link

Ethan-Arrowood commented Jun 29, 2020

We are hitting this bug in our type definitions for Fastify. See: fastify/fastify#2350

Is there a reason this keeps getting bumped the next version of TS? Anything we can do to help solve it? Is there a recommended workaround?

@orta
Copy link
Contributor

orta commented Jul 1, 2020

This issue is fixed in 3.9 judging on both of the playgrounds - @Ethan-Arrowood you might be looking at a different bug

@orta orta closed this as completed Jul 1, 2020
@Ethan-Arrowood
Copy link

@orta please have a look at this playground I've created. Am I doing something wrong?

@Ethan-Arrowood
Copy link

Ethan-Arrowood commented Jul 1, 2020

Ahh taking a second look at this issue it seems its more about whats returned from the async functions. But the question still stands for why my playground is not working... should I open a new issue for it?

I realize my mistake now keep this closed; not a bug with TS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

No branches or pull requests

6 participants