Reputation: 2964
I have a function myFunc
which takes one argument. This argument is an object, where each property of the object is an array containing two elements:
myFunc({
prop1: [value1, (value1) => { /*...*/ }],
prop2: [value2, (value2) => { /*...*/ }],
});
As you can see, the first element can be anything (some user-specified value), and the second element is a function.
The function defined for the second element takes the first element as an argument.
For example:
// both functions returns true
myFunc({
prop1: ["hello", (str) => str === "hello"],
prop2: [5, (num) => num === 5],
});
This is working as expected, but I cannot figure out how to infer the type of the first element, so that I can properly type the parameter of the function defined for the second element.
Essentially what I want is something like this:
// How do I infer the type of U from the first array element?
const myFunc = <T extends { [key: string]: [U, (u: U) => any] }>(t: T) => {
// ...
}
The myFunc
function takes a string-keyed object, with values that are arrays of two elements, where the type of the first element is the same type as the parameter of the function defined for the second element.
Is there some way I can infer the type of U
from the first element, so that I can apply this type to the second element?
Upvotes: 3
Views: 1330
Reputation: 2555
TypeScript compiler is not perfect, it can't infer everything (yet), there are some details you (as developer) have to tell him. When you pass a function as an argument, you have to declare types of parameters that this function accepts. Otherwise TS compiler can not protect you (in other words: checking type of 'num' & 'str' arguments would be only possible in runtime) The best I was able to do to type your example is:
type TStingFunk = (y: string) => boolean
type TNumFunk = (y: number) => boolean
type PropTuple = [x: number, funk: TNumFunk ] | [x: string, funk: TStingFunk ]
interface IProp {
prop1: PropTuple,
prop2: PropTuple,
}
type TFunc = (prop: IProp) => void;
const myFunc:TFunc = ({
prop1,
prop2,
}) => {}
myFunc({
prop1: ["hello", (str: string) => str === "hello"],
prop2: [5, (num: number) => num === 5],
})
this compiles without errors and TS protects you from case when you pass wrong params to myFunc
Upvotes: 1