镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Parameter of a callback without a specified type next to it breaks code. #29799

Closed

Description

TypeScript Version: 3.4.0-dev.20190207, 3.3.0

Search Terms:
type parameter, callback

Code

interface Bar<T> {
    <B_RETURN>(
        a: (aParam: B_RETURN) => any,
        b: (bParam: T) => B_RETURN // B_RETURN is supposed to be inferred from here
        ): any
}

declare const bar: Bar<any>

bar((aParam) => 1, () => 'abc') // OK! `aParam` is `string`
bar((aParam) => 1, (bParam) => 'abc') // `aParam` is `{}`. Why?
bar((aParam) => 1, (bParam: any) => 'abc') // `aParam` is `string`. Again, why?
let arg2 = (bParam) => 'abc' ; bar((aParam ) => 1, arg2) // `aParam` is `string`. Again, why?

Expected behavior:
aParam should be string in each of the four examples

Actual behavior:
aParam is for some reason {} instead of string in the second example

Playground Link: link

I would be very grateful if someone can give me some quick directions (Is it a bug? What am I missing?). My work depends on it in a great degree.

P.S. Asked on stackoverflow and got no answer.

Activity

  1. RyanCavanaugh commented on Feb 14, 2019

    @RyanCavanaugh
    Member

    This is basically the dual of #29791 - inference on functions proceeds left-to-right, so during the inference of aParam in the first function we have not yet examined the body of the second function expression to determine its return type (which we believe will be context-sensitive, in other words depends on its parameter type).

  2. anurbol commented on Feb 15, 2019

    @anurbol
    Author

    Ryan Cavanaugh (@RyanCavanaugh) Thank you, made it very clear for me. Except one part:

    which we believe will be context-sensitive, in other words depends on its parameter type

    I am not sure how the return type can depend on parameter type if it's clear that the function returns string, because it returns string literal. Moreover, I am confused by the fact that unknown parameter (bParam) and parameter of type any (bParam: any) lead to different results. Maybe this is worth fixing? I feel that it's wrong. It's just a suggestion, because, I am satisified with the provided answer already and this issue can be closed.

    Again, thank you very much, I hate mysteries and love when they become simple things, like you made them for me.

  3. RyanCavanaugh commented on Feb 15, 2019

    @RyanCavanaugh
    Member

    I am not sure how the return type can depend on parameter type if it's clear that the function returns string, because it returns string literal.

    We don't have a separate pass to say "Go dive into the function and check to see if all its return statements don't rely on its parameter type" - doing so would be expensive in light of the fact that extremely few real-world functions actually behave like that in practice.

    Moreover, I am confused by the fact that unknown parameter (bParam) and parameter of type any (bParam: any) lead to different results.

    An unannotated parameter isn't the same as any -- it's one that we're going to try to infer a type for. Functions with type annotations aren't context-sensitive, thus get treated differently in the inference process.

  4. anurbol commented on Feb 16, 2019

    @anurbol
    Author

    Ryan Cavanaugh (@RyanCavanaugh) Wow. That's another valuable insight of how the compiler works, thank you so much! If only there would be a way to know these algorithms of TS compiler without looking at it's source code and bothering you in issues.

    I think I will close this issue as I don't have other questions and the "Design Limitation" badge probably means I should close it.

    Thanks again!

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions