Search code examples
typescripttypescript-genericsnested-generics

Typescript: How to define a function that references an object using generics


How does one define a function based on keys of an object using generics. The actual use case has more keys and values so I prefer not to define it explicitly.

const obj = {
    a: {
        1: 1,
        2: 2,
        3: 3,
    },
    b: {
        1:1,
        2:2,
        4:4
    },
};

// My best attempt
const fn = <T extends keyof typeof obj>(key1: T, key2: keyof T) => {
    return obj[key1][key2];
}

Error: Type 'keyof T' cannot be used to index type '{ a: { 1: number; 2: number; 3: number; }; b: { 1: number; 2: number; 4: number; }; }[T]'


Solution

  • You need to add some more generic parameters:

    const obj = {
        a: {
            1: 1,
            2: 2,
            3: 3,
        },
        b: {
            1:1,
            2:2,
            4:4
        },
    };
    
    const fn = <O, T extends keyof O, U extends keyof O[T]>(o: O, key1: T, key2: U) => {
        return o[key1][key2];
    }
    
    fn(obj, 'a', 1) // ok
    fn(obj, 'a', 6) // error
    

    TS playground