Issue
I have an interface with a generic field, sort of like
interface HasVal<T> {
val: T
}
I want to create a function like get_val which accepts any HasVal implementer and returns it's val:
function get_val<T, Hv extends HasVal<T>>(hv: Hv): T {
return hv.val
}
This doesn't work, because T doesn't get narrowed for some reason:
class MyVal {
val = "hello world!"
}
let u = get_val(new MyVal());
// type of u is unknown :(
Is there a type signature for get_val that will return the proper type without requiring the caller to specify it?
Solution
The problem with
declare function get_val<T, Hv extends HasVal<T>>(hv: Hv): T;
is that generic constraints are not used as inference sites for other generic type arguments. (Such a feature was suggested at microsoft/TypeScript#7234 but eventually declined in favor of other techniques.) So while Hv can be inferred from the hv argument, T cannot be inferred from the Hv extends HasVal<T> constraint. There's pretty much nowhere from which T can be inferred, so it falls back to the implicit unknown constraint, and you get the undesirable behavior.
Given this example, I'd be inclined to just remove the Hv type parameter entirely. If you want to infer T from an input of type HasVal<T>, tell the compiler that hv is of type HasVal<T> directly, not indirectly via a constraint:
function get_val<T>(hv: HasVal<T>): T {
return hv.val
}
And now things behave as desired:
let u = get_val(new MyVal());
// let u: string
T is inferred as string because a MyVal instance is seen as a valid HasVal<string>.
Answered By - jcalz
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.