After defining the types below
type Tool = 'network_query' | 'cluster'
type Network = 'one' | 'two' | 'three'
class QueryOneParams {...}
class QueryTwoParams {...}
class QueryThreeParams {...}
class ClusterParams {...}
The goal is to establish a connection between different combinations of Tool
and Network
, enabling a structure like this:
const queryParamsLookup = {
'one': QueryOneParams,
'two': QueryTwoParams,
'three': QueryThreeParams
}
type Job<Tool, Network> = {
id: string,
params: JobParams<Tool, Network>
}
This would mean that:
corresponds toJobParams<'network_query', 'one'>
QueryOneParams
corresponds toJobParams<'network_query', 'two'>
QueryTwoParams
corresponds toJobParams<'network_query', 'three'>
QueryThreeParams
JobParams<'cluster'>
corresponds toClusterParams
,JobParams<'cluster', 'one'>
, andJobParams<'cluster', 'two'>
are not validJobParams<'cluster', 'three'>
To achieve this, there's a need to define that the second generic parameter 'one' | 'two' | 'three'
is only used if the first parameter is 'network_query'
. As far as I know, TypeScript does not support optional generic parameters based on another parameter's type.
Is this accurate? Hopefully, it's possible!
Alternatively, a helper type has been created:
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']
The definition of Job
has been updated to:
type Job<JobType> = {
id: string,
params: JobParams<JobType>
}
Despite these changes, there are challenges with type inference within 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
To address the issue with type inference, the following workaround was implemented:
type JobParams<T extends JobType> = T extends ['network_query', infer N] ?
N extends Network ?
typeof queryParamsLookup[N] // No error
: ClusterParams
: ClusterParams
However, autocomplete performance remains subpar when typing certain expressions:
const params: JobParams<['
In situations like this, VSCode fails to offer suggestions for 'cluster' | 'network_query'
Overall, it seems like an uphill battle. Is there a fundamental mistake in this approach?