Open
Description
TypeScript Version:
4.0.2
Search Terms:
Circular type parameter constraint, functional property inference, function parameter inference, function argument inference
Code:
declare const m: <T extends M<T>>(m: T) => T
type M<Self, K = Exclude<keyof Self, "k" | "t">> =
{ a?: number
, b?: number
, c?: number
, d?: number
, k?: K
, t?: (k: K) => void
}
// :)
// Case 1
m({
a: 1,
b: 2,
k: "a"
})
// :)
// Case 2
m({
a: 1,
b: "x", // expected error
k: "c" // expected error
})
// :(
// Case 3
m({ // type parameter becomes `unknown` (probably because t's first parameter is `any` initially kinda?)
a: 1,
b: 2,
k: "a",
t: k => {} // k is inferred as `never` (instead of `"a" | "b"`)
})
// :|
// Case 4
m({
a: 1,
b: 2,
k: "a",
t: (k: "a" | "b") => {} // have to explicitly type `k` which could have been inferred :(
})
Expected behavior:
The parameter k
of t
should be inferred as "a" | "b"
. As property k
already gets inferred in Case 1 & 2, so why not the k
parameter of t
Actual behavior:
The parameter of t
is inferred as never
and T
in inferred as unknown
. I assume first T
gets resolved to unknown
as t
is initially inferred as (k: any) => void
which does not satisfy the constraint of m
.