Description
Bug Report
🔎 Search Terms
parameter 'x' implicitly has type 'any'
type inference
discriminated union
discriminant property
type narrowing of parent object
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ
⏯ Playground Link
Playground link with relevant code
💻 Code
type Closure<T> = { arg: T, fn: (_: T) => void };
const a: Closure<`x${string}`> | Closure<number> = {
arg: 0,
// x is inferred as number, because of arg above
fn: (x) => {}
}
const b: Closure<string> | Closure<number> = {
arg: 0,
// x cannot be inferred (parameter 'x' implicitly has type 'any')
fn: (x) => {}
}
🙁 Actual behavior
Inference of the parameter to the function field fn
is inconsistent across the two objects. The only difference is the type T
in Closure<T> | Closure<number>
for the object type:
- When
T
isboolean
,"a" | "b"
,null
or even`x${string}`
, the type ofx
asnumber
is correctly inferred whenarg
is set to0
. - When
T
isstring
,never
,number[]
, inference ofx
as typenumber
is not possible.
See TS playground link for more examples of which types inference is possible for.
There is no immediately obvious pattern as to what types result in possible inference and what types preclude it.
I'm no expert on how this inference is accomplished, but if it is at all similar to type narrowing then this comment #30506 (comment) is the closest explanation I can find. Maybe type inference works when T
is boolean ~ true | false
and "a" | "b"
because arg
is then discriminant property. Even in this case, it would seem a field of type `x${string}`
would be a discriminant property(?) and I can't wrap my head around why a field of type string
could not be a discriminant property if one of type `x${string}`
can be
🙂 Expected behavior
Type inference of the parameter x
to property fn
is consistent across types T
in Closure<T> | Closure<number>
when arg
is set to 0
and 0
is not an instantiation of T
OR
If type inference is not meant to be consistent due to a design limitation (e.g. as in #33205 (comment)), this behavior difference and any associated design limitation is better/more clearly documented -- I'd love to see something on discriminant properties in official documentation, as I found the Github threads a little hard to follow