Lukor
Lukor

Reputation: 1707

Typescript keyof where value has type

I am trying to write a function in Typescript which takes:

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

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

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

Related Questions