#Narrowing in Switch statement based on Generic Type

1 messages · Page 1 of 1 (latest)

rose wing
#

I am trying to type an API, that can be called with multiple messages. Depending on the message (string), the data parameter’s type and response’s type are different. I am setting this up using generics. In theory I think this should work, and when I hover over the variables the generic types are shown correctly, but they are not narrowed down to the correct type: if I switch depending on the message, the data object is still a tuple of all possible data types, and so is the response.

What can I do to narrow the type of the data object and return type in the switch statements?

jaunty citrusBOT
#
c._l#0

Preview:```ts
interface ApiFunctions {
foo: {
data: {
param: string
}
returnValue: (a: number) => void
}
bar: {
data: {
id: number
}
returnValue: string
}
}

type Api = {
request: <K extends keyof ApiFunctions>(
message:
...```

mental nacelle
#

You can't narrow generic type parameters.

rose wing
#

But when I hover over the code, typescript understands that message is of type K and data is type ApiFunctions[K].data – shouldn’t it then be able to use that, when within the switch statement message (and therefore K) must be "foo" and therefore data must be ApiFunctions["foo"].data?

mental nacelle
#

message being 'foo' does not mean T is 'foo', for example:

api.request<'foo' | 'bar'>('foo', { id: 42 })
rose wing
#

hm, interesting, that makes sense

#

is there a better way to write T extends keyof ApiFunctions as in “is one specific key of ApiFunctions”?

mental nacelle
#

There is not, no.

#

If your return type didn't also depend on message, then it could be done; but that's not your case.

#

Depends on what your request actually wants to achieve, either:

  • I don't intend for this to be fully type safe (eg I trust my API) and I'm not going to do any validation, so this is just purely for better autocomplete/basic type checking. In that case your request function body basically should have no logic at all and just sending out the request, and it's acceptable to just type assert inside the request implementation.
  • I do want this to be fully type safe including validating API return. In that case you might as well just split up the functions into requestFoo/requestBar, since the validation logic will be different anyways.
rose wing
#

yes, I think I will create the api as an object with a function for every message

#

thank you for the explanation, that was very helpful!