I'm having a little trouble understanding how string enums behave when using them to index types. It seems like sometimes TS recognizes that a string enum's value is an extension of keyof some type, and other times it doesn't. To illustrate:
enum Key {
FOO = "foo",
}
type MyObj = {
foo: string
}
So, an enum of the properties of a type (i.e., you can index into obj:MyObj using obj[Key.FOO]).
Now I want to define another type that will lookup a value in the MyObj type to determine if it is a keyof that type and, if so, use the type of that key's value:
type FunctionReturn<T extends Record<string, any>,U extends keyof T> = {
returnValue: U extends keyof T ? T[U]: never
}
If I use that type as follows, though, I get an error.
function myFunction(value: MyObj[Key.FOO]):FunctionReturn<MyObj, Key.FOO>{
return {returnValue: "a string"}
}
Namely, TS does not find the U extends key of T (where U is an enum member) to be satisfied in typing returnValue even though it accepted it as meeting the constraint of the FunctionReturn type.
The error goes away completely if I pass the actual string literal as the parameter.
function myOtherFunction(value: MyObj[Key.FOO]):FunctionReturn<MyObj, "foo">{
return {returnValue: "a string"}
Why is that? It seems to me if TS excepted Key.FOO as a valid extension of keyof MyOb in the generic constraint, it should also meet the conditional. What am I missing?
Here's the playground.
Much appreciated, as always.