Open
Description
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.