I have a data structure called AccountDefinition
which is structured like this:
something: {
type: 'client',
parameters: {
foo: 3
}
},
other: {
type: 'user',
parameters: {
bar: 3
}
},
...
The TypeScript declaration is functioning properly, but I am currently facing difficulties while trying to create a "generator" function (doThings
) and struggling with how to correctly define its types. I am considering refactoring all these types as well.
export interface Spec {
type: `${SpecType}`
parameters: unknown
}
export interface UserSpec extends Spec {
type: `${SpecType.USER}`
parameters: UserSpecParameters
}
export interface ClientSpec extends Spec {
type: `${SpecType.CLIENT}`
parameters: ClientSpecParameters
}
export interface AccountDefinition {
[k: string]: UserSpec | ClientSpec
}
export enum SpecType {
USER = 'user',
CLIENT = 'client'
}
export type SpecParametersMap = {
user: {
bar?: number
}
client: ClientSpecParameters
}
export interface UserSpecParameters {
bar?: number
}
export interface ClientSpecParameters {
foo: number
}
export const doThing = <T extends SpecType>( // Preferably not generic if inference works from type
type: T,
parameters: SpecParametersMap[T]
): void => {
const account: AccountDefinition = {
// Example
foo: {
type: 'client',
parameters: {
foo: 3
}
},
// TS Error:
// Type '{ parameters: SpecParametersMap[T]; type: T; }' is not assignable to type 'UserSpec | ClientSpec'.
// Type '{ parameters: SpecParametersMap[T]; type: T; }' is not assignable to type 'ClientSpec'.
// Types of property 'type' are incompatible.
// Type 'T' is not assignable to type '"client"'.ts(2322)
data: {
parameters,
type
}
}
}
doThing(SpecType.CLIENT, { foo: 4 })
Test it on the Playground here.