Given the following types
type Tool = 'network_query' | 'cluster'
type Network = 'one' | 'two' | 'three'
class QueryOneParams {...}
class QueryTwoParams {...}
class QueryThreeParams {...}
class ClusterParams {...}
I'm trying to define a mapping between combinations of Tool and Network so that I could write something like this:
const queryParamsLookup = {
'one': QueryOneParams,
'two': QueryTwoParams,
'three': QueryThreeParams
}
type Job<Tool, Network> = {
id: string,
params: JobParams<Tool, Network>
}
where
JobParams<'network_query', 'one'>resolves toQueryOneParamsJobParams<'network_query', 'two'>resolves toQueryTwoParamsJobParams<'network_query', 'three'>resolves toQueryThreeParamsJobParams<'cluster'>resolves toClusterParamsJobParams<'cluster', 'one'>,JobParams<'cluster', 'two'>andJobParams<'cluster', 'three'>are invalid
That would require me to somehow define that the second generic parameter 'one' | 'two' | 'three' is only used and required, if the first parameter is 'network_query'. Afaik, Typescript does not support optionally defined generic parameters based on the type of another parameter.
Is that correct? I'd love to be wrong here :)
As an alternative, I have defined a helper type like so:
type NetworkQueryJobType = {
[N in keyof typeof queryParamsLookup]: ['network_query', N]
}[keyof typeof queryParamsLookup]
// ['network_query', 'one'] | ['network_query', 'two'] | ['network_query', 'three']
type JobType = NetworkQueryJobType | ['cluster']
// ['network_query', 'one'] | ['network_query', 'two'] | ['network_query', 'three'] | ['cluster']
and changed the definition of Job to
type Job<JobType> = {
id: string,
params: JobParams<JobType>
}
with this approach, I'm having trouble getting type inference to work properly in the mapper type JobParams:
type JobParams<T extends JobType> = T extends ['network_query', infer N] ?
typeof queryParamsLookup[N] // Error: N is not compatible with 'one' | 'two' | 'three'
: ClusterParams
I can work around the type inference issue with:
type JobParams<T extends JobType> = T extends ['network_query', infer N] ?
N extends Network ?
typeof queryParamsLookup[N] // No error
: ClusterParams
: ClusterParams
All of that however still leaves me with poor autocomplete performance when typing, for example:
const params: JobParams<['
VSCode will not suggest 'cluster' | 'network_query'
All in all, I feel like fighting a losing battle here. Am I doing something fundamentally wrong?
QueryOneParamsas an expression inqueryParamsLookup?QueryOneParamsand friends are classes. I'll change it in the question. Thank's for catching this :)Jobtype is erroring. Please fix it and update the link in the question.