Get the value of a parameter and make it the type of another parameter

The behavior I’m looking for can be implemented with overloading:

function fun(elType: "input", params: Input): number;
function fun(elType: "swtich", params: Switch): number;
function fun(){
  return 2
}

Where if I run:

fun("swtich", SOMETHING_OF_SHAPE_SWITCH) //compiles
fun("input", SOMETHING_OF_SHAPE_INPUT) // error
fun("input", SOMETHING_OF_SHAPE_INPUT) //compiles

I was wondering if it can be done by checking the parameter directly:

interface Input {
  a: 2
}

interface Switch {
  b: 2
}

type ElType = {
  input: Input,
  switch: Switch,
}

const fun = <T extends keyof ElType>(elType: keyof ElType, params: ElType[typeof elType]) => { }

That’s as close as I got but it allows both:

fun("input", {
  b: 2
})


fun("input", {
  a: 2
})

It seems that I’m close, but I’m a) not quite sure what’s happening in this last example and b) not sure how to achieve the desired bahaviour.

It seems what I want to do is:

const fun = <T extends keyof ElType>(elType: keyof ElType, params: ElType[elType]) => {}

But I get the error: type 'elType' cannot be used as an index type.

Here’s a tsplayg4round I’m using if you want to play around.

I’ve seen several libraries implement this pattern so I was wondering what’s the most idiomatic way of doing it.

>Solution :

You’ve defined the generic T but haven’t used it! TypeScript doesn’t know what to do with it so it ignores it.

<T extends keyof ElType>(elType: T, params: ElType[T]) => ...

Using it here allows TypeScript to infer what T is from elType, and once it knows what T is, you can use ElType[T] to get the right params.

Leave a Reply