I have a type with key-value pairs, where keys are React component names and values are the values they take as props. What I am trying to do is to type an array of types containing the type field, which is also the exact name of a component, and a getter
and setter
functions that use component values types.
type ElementValues = {
text: string,
checkbox: boolean
}
type ElementType = keyof ElementValues
type Value<Type extends ElementType> = ElementValues[Type]
type Test = {
[Type in ElementType]: {
type: Type
getter: () => Value<Type>
setter: (value: Value<Type>) => any
}}[ElementType]
const testList: Array<Test> = [{
type: 'checkbox',
getter: () => 'test,
setter: (value) => ({ })
}]
What I can get is the array with elements that do not care about the given component name and take all possible component value types as setter and getter params/return types.
In the above example, getter
should require boolean
, as for checkbox value, and setter
should have a value type of boolean
, not boolean | string
.
CodePudding user response:
The following would do the trick. Just use discriminated unions. This way the array elements are going to be discriminated by the type
field (text
or checkbox
).
type ElementValues = {
text: string,
checkbox: boolean
}
type ElementType = keyof ElementValues
type Value<Type extends ElementType> = ElementValues[Type]
type Test<Type extends ElementType> = {
type: Type
getter: () => Value<Type>
setter: (value: Value<Type>) => any
}
// Here - Discriminated Unions
type Elements =
| Test<'checkbox'>
| Test<'text'>
const testList: Array<Elements> = [
{
type: 'text',
getter: () => 'test1',
setter: (value) => ({ })
},
{
type: 'checkbox',
getter: () => true,
setter: (value) => ({ })
}
]
CodePudding user response:
It seems that adding helper type Elements
solved the problem.
Based on @lepsch answer:
type ElementValues = {
text: string,
checkbox: boolean
}
type ElementType = keyof ElementValues
type Value<Type extends ElementType> = ElementValues[Type]
type Test<Type extends ElementType> = {
type: Type
getter: () => Value<Type>
setter: (value: Value<Type>) => any
}
type Elements = {
[Type in ElementType]: Test<Type>
}[ElementType]
const testList: Array<Elements> = [
{
type: 'text',
getter: () => 'test',
setter: (value) => ({ })
},
{
type: 'checkbox',
getter: () => true,
setter: (value) => ({ })
}
]