Skip to content

Parameter type isn't inferred in values of mapped type with as. #46602

Description

@strout

Bug Report

I came across this odd behavior while doing Day 5 of "Type | Treat".

🔎 Search Terms

as mapped function parameter infer

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about Type System Behavior.

I tried every Playground version with as support.

⏯ Playground Link

Playground link with relevant code

💻 Code

function bug<Es extends 'foo' | 'bar'>(_: { [E in Es as `on${E}`]: (e: string) => void }) {
}

bug({
  onfoo(_e) {}, // _e: any; onfoo: (e: string) => void
  onbar(_e) {}  // _e: any; onbar: (e: string) => void
})

function workaround_1<Es extends 'foo' | 'bar'>(_: { [E in `on${Es}`]: (e: string) => void }) {
}

workaround_1({
  onfoo(_e) {}, // _e: string
  onbar(_e) {}  // _e: string
})

function workaround_2<Es extends 'foo' | 'bar'>(_: Es extends never ? {} : { [E in Es as `on${E}`]: (e: string) => void }) {
}

workaround_2({
  onfoo(_e) {}, // _e: string
  onbar(_e) {}  // _e: string
})

🙁 Actual behavior

The types of onfoo and onbar are correctly inferred as (e: string) => void but the parameter _e is incorrectly typed as any instead of string.

🙂 Expected behavior

I would expect _e to have type string, because it's known that the function has type (e: string) => void. I provided two variations that are typed correctly -- one without using as, and one forcing the type to be conditional on Es. All three should be equivalent. I'm especially surprised that bug and workaround_2 behave differently since it's (presumably) just forcing Es to be evaluated slightly earlier.

Activity

  1. changed the title [-]Parameter type isn't inferred in values of mapped type with "as".[/-] [+]Parameter type isn't inferred in values of mapped type with `as`.[/+] on Oct 30, 2021
  2. andrewbranch commented on Nov 1, 2021

    @andrewbranch
    Member

    workaround_2 is pretty weird 👀

  3. ahejlsberg commented on Nov 2, 2021

    @ahejlsberg
    Member

    We currently only implement inference to mapped types without as clauses. In none of the examples do we actually infer anything for Es, rather we simply default to the constraint 'foo' | 'bar', which so happens to match the supplied arguments. So, there's an implied request for a new feature here.

    That said, it does seem like we should contextually type _e for each of the methods in the call to bug. We can look at fixing that, but without actual support for inference to mapped types with as clauses, it wouldn't help much.

  4. strout commented on Nov 2, 2021

    @strout
    Author

    That makes sense. As you said, when removing onbar from each argument, bug and workaround_1 calls are rejected because of the constraint defaulting. I see workaround_2 is still accepted though. (Playground)

    This wasn't from any real-world code, so I'll have no complaints if it turns out to be too obscure to be worth addressing. 😃

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

Metadata

Metadata

Labels

Needs InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions