Reputation: 1707
I am trying to write a function in Typescript which takes:
X
(in this example: boolean)(eg.
{someValue: true}
-> key="someValue")
Currently, my approach is as follows:
function myFunction<
T extends Record<K, boolean>, // the type of the object
K extends keyof T, // the key which points to X
>(
obj: T,
objKey: K,
) {
const x: boolean = obj[objKey];
}
This works as long as I only need the object to be of type T
and no additional types. However, I now need an object which implements both T
(an object with a boolean member) and AdditionalData
. However, if I replace T extends Record<...>
with T extends Record<...> & AdditionalData
, the type check of course fails.
The solution I came up with was to introduce another generic type L
, which only includes data from SomeInterface
and make K
depend on that:
function myFunction<
L extends Record<K, boolean>, // the type containing the boolean value
K extends keyof L, // the key which points to X,
T extends L & AdditionalData, // the type of the object
>(...) {}
However, this does not work either.
Is there any way to force the value pointed to by a key to be of a specific type?
EDIT: alternatively, is there a way to exclude a specific value from keyof
? That way, I could just exclude any additional types from K...
Upvotes: 4
Views: 3428
Reputation: 249536
Typescript doesn't always reason very well about the type of generic parameter type fields. I'm not sure exactly what is causing it to not recognize the fact that obj[objKey]
is a boolean
but the simple workaround is to use an extra variable:
interface AdditionalData {
a: number,
b: string
}
function myFunction<
T extends Record<K, boolean> & AdditionalData, // the type of the object
K extends keyof T, // the key which points to X
>(
obj: T,
objKey: K,
) {
const o : Record<K, boolean>= obj; // assignable
const x: boolean = o[objKey]; // access works ok
}
Upvotes: 1