'Build a complex type from Union type
I'm trying to build a type with two layers from a flat union type
Here's my code:
type TextVariants =
| {
size: 'tiny'
// available variants for this size
variants:
| 'regularNormal'
}
| {
size: 'super'
// available variants for this size
variants:
| 'regularNone'
}
type TextSizesProps = {
[k in TextVariants['size']]: {
css: Object
variants: {
[v in TextVariants['variants']]: Object
}
}
}
const textSizes: TextSizesProps = {
tiny: {
css: {
fontSize: '$tiny',
},
variants: {
// Here TS is complaining about missing "regularNone" but shouldn't
regularNormal: {
lineHeight: '$normal',
fontWeight: '$regular',
},
},
},
super: {
css: {
fontSize: '$super',
},
variants: {
// same
regularNone: {
lineHeight: '$none',
fontWeight: '$regular',
},
},
},
},
}
I have different names for each text size, and I need it to be recognized
Here's a link for the typescript playground
Any help is appreciated
Solution 1:[1]
You should try it like this:
type TextSizesProps = {
[V in TextVariants as V["size"]]: {
css: Object
variants: {
[v in V["variants"]]: Object
}
}
}
Creating a mapped type out of TextVariants['size']
and then again out of TextVariants['variants']
will lead to a union which allows all variants for all sizes.
But if you map over the different TextVariants
you can store each variant inside V
. V
now represents a specific variant and can be used to access the variants variant
and size
properties.
Solution 2:[2]
If you're open to it, you can change the definition of the TextVariants
type to be an object type so you can iterate the keys in the TextSizesProps
type.
For example:
type TextVariants = {
tiny:
| "regularNormal";
super:
| "regularNone";
}
type TextSizesProps = {
[K in keyof TextVariants]: {
css: Object;
variants: {
[V in TextVariants[K]]: Object;
}
}
}
or to allow for adding more fields in the future:
type TextVariants = {
tiny: {
variants:
| "regularNormal";
};
super: {
variants:
| "regularNone";
};
}
type TextSizesProps = {
[K in keyof TextVariants]: {
css: Object;
variants: {
[V in TextVariants[K]["variants"]]: Object;
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tobias S. |
Solution 2 | Henry Woody |