Skip to content

Strange tuple typing #3954

Closed
Closed

Description

function f<T extends { "0": (p1: number) => number }>(p: T): T
{
    return p;
}

var v = f([x => x]); // v is typed as [{}]. Expected [number=>number]

Activity

  1. sophiajt commented on Jul 21, 2015

    @sophiajt
    Contributor

    In your example, there isn't really a type to bind to. You're saying T extends a known type, but there's not enough information to know which resulting type. It's like saying "pick a subtype of { "0": (p1: number) => number }, but I won't tell you which one".

    The x=>x isn't enough to help figure it out either.

    When the compiler hits that point, it chooses a conservative answer, like {}, to help prevent other errors from slipping through.

  2. osdm commented on Jul 21, 2015

    @osdm
    Author

    jonathandturner Could you please point to paragraph in the specification which discusses this process of choosing a conservative answer?

  3. osdm commented on Jul 21, 2015

    @osdm
    Author

    And one more question. If we have a tuple as a result, then we have a contextual type with a property "0" for our array literal. But at the same time, we don't have a contextual type for array element. How could it be?

  4. RyanCavanaugh commented on Jul 21, 2015

    @RyanCavanaugh
    Member

    This isn't specific to tuples. You see the same behavior with object literals:

    function f<T extends { q: (p1: number) => number }>(p: T): T {
        return p;
    }
    
    var v = f({q: x => x}); // v is typed as [{}]. Expected [number=>number]

    We don't meaningfully contextually type x => x because the parameter type is just T. Arguably we should use base constraint of a type parameter when contextually typing by it, which should make all these examples "just work". Anders Hejlsberg (@ahejlsberg) ?

  5. osdm commented on Jul 21, 2015

    @osdm
    Author

    Ryan Cavanaugh (@RyanCavanaugh) Well, at least there should be an compilation error, because [{}] is not assignable to { "0": (p1: number) => number }. Because of this IMHO this is a bug.

  6. RyanCavanaugh commented on Jul 21, 2015

    @RyanCavanaugh
    Member

    That's a good point

  7. JsonFreeman commented on Jul 21, 2015

    @JsonFreeman
    Contributor

    I'm debugging this now. I'll be able to give you an answer soon about what is going on.

  8. JsonFreeman commented on Jul 21, 2015

    @JsonFreeman
    Contributor

    jonathandturner Ryan Cavanaugh (@RyanCavanaugh) Dmitry Osinovskiy (@osdm) We do use the base constraint for contextual typing, as of recently, #3822. So there is something else amiss.

  9. JsonFreeman commented on Jul 21, 2015

    @JsonFreeman
    Contributor

    Ok, turns out we are leaking an internal compiler type that looks like {}. It happens whenever you try to infer a type for a type parameter, and the type parameter contains the anyFunctionType, but isn't directly the anyFunctionType.

  10. JsonFreeman commented on Jul 21, 2015

    @JsonFreeman
    Contributor

    I am adding a rule in the subtype relation to fix this.

  11. JsonFreeman commented on Jul 21, 2015

    @JsonFreeman
    Contributor

    Ok, the new rule is that a type with signatures is not a subtype of the anyFunctionType. It is assignable, but it's not a subtype.

  12. locked and limited conversation to collaborators on Jun 19, 2018
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

    BugA bug in TypeScriptFixedA PR has been merged for this issue

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions