I would like to create a function A, which returns function B, where the valid inputs to function B depend on the inputs to function A.
The code below attempts to achieve this, but the linter expects the input for the second function to only ever be "a". I’d like valid inputs to be "a", "b", or "c" if "1" is passed into the first function.
const dictionary = {
"1": {
a: "a",
b: "b",
c: "c"
},
"2": {
a: "a",
d: "d"
}
}
const func = (componentKey: keyof typeof dictionary) => {
const obj = dictionary[componentKey];
return (nestedKey: keyof typeof obj) => {
return dictionary[componentKey][nestedKey];
};
};
// Argument of type '"b"' is not assignable to parameter of type '"a"'. ts(2345)
const test = func("1")("b")
How can I set up a type structure such that func("1")("b") is valid but func("1")("d") is not?
>Solution :
You can use a conditional type to define the input types of function B based on the input of function A.
type DictionaryKeys<T> = T extends keyof typeof dictionary ? keyof typeof dictionary[T] : never;
const func = <T extends keyof typeof dictionary>(componentKey: T) => {
const obj = dictionary[componentKey];
return (nestedKey: DictionaryKeys<T>) => {
return dictionary[componentKey][nestedKey];
};
};
// Valid input
const test1 = func("1")("b");
// Invalid input
const test2 = func("1")("d");