How can I index a generic with an with the argument passed in to function in Typescript

Suppose I have an interface in typescript as follows:

interface I1 {
    name: string,
    age: number
}

And I have another interface that accesses interface properties:

interface I2<T> {
    getValue: (arg0: keyof T) => any
}

I want to be able to pass in another interface into I2 such that you can only pass in keys of T and it will return the type of that key.

So If I have

const record: I2<I1> = new Record()

I want

const name = record.getValue('name')

to return a string and

const age = record.getValue('age') 

to return a number

The first part works – I can only pass in keys of I1
The second part doesn’t work.

I tried

interface I2<T> {
    getValue: (arg0: keyof T) => T[keyof T]
}

but this makes that any call to getValue will return a union number|string.

I tried

interface I2<T> {
    getValue: (arg0: keyof T) => T[arg0]
}

but this isn’t valid typescript

>Solution :

In order for getValue() to represent a relationship between the particular key input and the type of the output, you’ll need to make it a generic method with its own type parameter K constrained to keyof T, like this:

interface I2<T> {
    getValue: <K extends keyof T>(k: K) => T[K]
}

Now things should behave as expected:

interface I1 {
    name: string,
    age: number
}

declare const record: I2<I1>;

const name = record.getValue('name')
// const name: string
const age = record.getValue('age');
// const age: number

Playground link to code

Leave a Reply