Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to typehint the keys of a nested object in TypeScript?

Tags:

typescript

I have some interfaces that all extend a base interface. e.g:

interface Base {
    sharedKey : "a" | "b"
}

interface ChildOne extends Base {
    sharedKey : "a",
    keyOne : "child_one"
}

interface ChildTwo extends Base {
    sharedKey : "b",
    keyTwo : "child_two"
}

All the extended interfaces define a shared key that narrows the definition. I'm trying to implement a feature that I've seen in many IDEs, which typehints the keys of nested objects. Consider a function such as this:

function doStuff( sharedKey, privateKey ) { // Something here};

This function will accept a key that is a or b, and based on that key, will detect whether privateKey is allowed to be keyOne or keyTwo.

For example this should be allowed:

doStuff( 'a', 'keyOne' ); // Allowed

But this should not:

doStuff( 'b', 'keyOne' ); // Error: keyOne does not exist on ChildTwo

Is this possible? I tried using template literals, but the problem is that the returned type from template literals was a string, and I can't use it as a Type.

Using Record<Unions['sharedKey'], Unions> (where Unions is a union of child interfaces ) provides some typehinting, which helps preventing keys that don't exist at all, but still allows using keys from other interfaces.

like image 448
Johansson Avatar asked Oct 18 '25 03:10

Johansson


1 Answers

One possible solution would be to use function overloads:

interface ChildOne {
    sharedKey : "a",
    keyOne : "child_one"
}

interface ChildTwo {
    sharedKey : "b",
    keyTwo : "child_two"
}

function doStuff( sharedKey: ChildOne['sharedKey'], privateKey: keyof ChildOne ):number
function doStuff( sharedKey: ChildTwo['sharedKey'], privateKey: keyof ChildTwo ):number
function doStuff( sharedKey: string, privateKey: string) { 
    // Something here
    return 0;
};

doStuff( 'a', 'keyOne' ); // Allowed
doStuff( 'b', 'keyOne' ); // Error: keyOne does not exist on ChildTwo
like image 96
Pablo Carrillo Alvarez Avatar answered Oct 20 '25 18:10

Pablo Carrillo Alvarez