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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With