Search code examples
javascripttypescripttypescript-typingsconditional-types

How to deduce the type of function argument by value of previous argument?


Using typescript, I want the compiler/IDE to deduce the type of argument when it can. How do I make it work ? First argument of my function is a string and it's value will decide the type of data that can be passed as the second argument. But I am not able to do that. I am sharing how I expected the compiler to work in this case but it is not helping me.

interface AuxType {
  name: string,
  user: number
}
type ValueType = AuxType[keyof AuxType]
function run(key: string, value: ValueType) {
  return dostuff(key, value)
}

run('name', "Stack") // Works as expected
run('user', 2)        // Works as expected
run('name', 2)        // Expecting this to error but it is not
run('user', "Stack") // Expect this to error but it works in typescript

Is it even possible in typescript ? Shouldn't this be possible with string literal value of the first argument ?


Solution

  • You need to use a generic. Right now, you are just defining ValueType as the union of the types of name and user, i.e. string | number, but it has no dependency on which key is actually passed to the function. To make the key and value depend you need to use a generic with your function, like this:

    function run<T extends keyof AuxType>(key: T, value: AuxType[T]) {
      return dostuff(key, value)
    }
    

    Now the key must be a keyof AuxType (thats what the extends is doing) and the value must be the corresponding type of that key in AuxType.