I'm developing React/React Native theme provider and want to have ability to specify spacing style properties base on sizes I define in theme. My current type of theme spacing looks like:
export interface Sizes { auto: "auto"; xxs: number; xs: number; s: number; m: number; l: number; xl: number; xxl: number; full: "100%";}type ValuesOfSizes = Sizes[keyof Sizes];type KeysOfSizes = keyof Sizes;export type MarginBase = Record<"base", Record<KeysOfSizes, Record<"margin", ValuesOfSizes>>>;export type MarginTop = Record<"top", Record<KeysOfSizes, Record<"marginTop", ValuesOfSizes>>>;export type MarginRight = Record<"right", Record<KeysOfSizes, Record<"marginRight", ValuesOfSizes>>>;export type MarginLeft = Record<"left", Record<KeysOfSizes, Record<"marginLeft", ValuesOfSizes>>>;export type MarginBottom = Record<"bottom", Record<KeysOfSizes, Record<"marginBottom", ValuesOfSizes>>>;export type MarginHorizontal = Record<"horizontal", Record<KeysOfSizes, Record<"marginHorizontal", ValuesOfSizes>>>;export type MarginVertical = Record<"vertical", Record<KeysOfSizes, Record<"marginVertical", ValuesOfSizes>>>;export type PaddingBase = Record<"base", Record<KeysOfSizes, Record<"padding", ValuesOfSizes>>>;export type PaddingTop = Record<"top", Record<KeysOfSizes, Record<"paddingTop", ValuesOfSizes>>>;export type PaddingRight = Record<"right", Record<KeysOfSizes, Record<"paddingRight", ValuesOfSizes>>>;export type PaddingLeft = Record<"left", Record<KeysOfSizes, Record<"paddingLeft", ValuesOfSizes>>>;export type PaddingBottom = Record<"bottom", Record<KeysOfSizes, Record<"paddingBottom", ValuesOfSizes>>>;export type PaddingHorizontal = Record<"horizontal", Record<KeysOfSizes, Record<"paddingHorizontal", ValuesOfSizes>>>;export type PaddingVertical = Record<"vertical", Record<KeysOfSizes, Record<"paddingVertical", ValuesOfSizes>>>;export interface Spacings { margin: MarginBase & MarginTop & MarginRight & MarginLeft & MarginBottom & MarginHorizontal & MarginVertical; padding: PaddingBase & PaddingTop & PaddingRight & PaddingLeft & PaddingBottom & PaddingHorizontal & PaddingVertical;}
And actual theme implementing spacing interface looks like:
const sizes: Sizes = { auto: "auto", xxs: 2, xs: 4, s: 8, m: 12, l: 16, xl: 24, xxl: 32, full: "100%",};const spacings: Spacings = { margin: { base: { auto: { margin: sizes.auto }, xxs: { margin: sizes.xxs }, xs: { margin: sizes.xs }, s: { margin: sizes.s }, m: { margin: sizes.m }, l: { margin: sizes.l }, xl: { margin: sizes.xl }, xxl: { margin: sizes.xxl }, full: { margin: sizes.full }, }, top: { auto: { marginTop: sizes.auto }, xxs: { marginTop: sizes.xxs }, xs: { marginTop: sizes.xs }, s: { marginTop: sizes.s }, m: { marginTop: sizes.m }, l: { marginTop: sizes.l }, xl: { marginTop: sizes.xl }, xxl: { marginTop: sizes.xxl }, full: { marginTop: sizes.full }, }, bottom: { auto: { marginBottom: sizes.auto }, xxs: { marginBottom: sizes.xxs }, xs: { marginBottom: sizes.xs }, s: { marginBottom: sizes.s }, m: { marginBottom: sizes.m }, l: { marginBottom: sizes.l }, xl: { marginBottom: sizes.xl }, xxl: { marginBottom: sizes.xxl }, full: { marginBottom: sizes.full }, }, left: { auto: { marginLeft: sizes.auto }, xxs: { marginLeft: sizes.xxs }, xs: { marginLeft: sizes.xs }, s: { marginLeft: sizes.s }, m: { marginLeft: sizes.m }, l: { marginLeft: sizes.l }, xl: { marginLeft: sizes.xl }, xxl: { marginLeft: sizes.xxl }, full: { marginLeft: sizes.full }, }, right: { auto: { marginRight: sizes.auto }, xxs: { marginRight: sizes.xxs }, xs: { marginRight: sizes.xs }, s: { marginRight: sizes.s }, m: { marginRight: sizes.m }, l: { marginRight: sizes.l }, xl: { marginRight: sizes.xl }, xxl: { marginRight: sizes.xxl }, full: { marginRight: sizes.full }, }, vertical: { auto: { marginVertical: sizes.auto }, xxs: { marginVertical: sizes.xxs }, xs: { marginVertical: sizes.xs }, s: { marginVertical: sizes.s }, m: { marginVertical: sizes.m }, l: { marginVertical: sizes.l }, xl: { marginVertical: sizes.xl }, xxl: { marginVertical: sizes.xxl }, full: { marginVertical: sizes.full }, }, horizontal: { auto: { marginHorizontal: sizes.auto }, xxs: { marginHorizontal: sizes.xxs }, xs: { marginHorizontal: sizes.xs }, s: { marginHorizontal: sizes.s }, m: { marginHorizontal: sizes.m }, l: { marginHorizontal: sizes.l }, xl: { marginHorizontal: sizes.xl }, xxl: { marginHorizontal: sizes.xxl }, full: { marginHorizontal: sizes.full }, }, }, padding: { base: { auto: { padding: sizes.auto }, xxs: { padding: sizes.xxs }, xs: { padding: sizes.xs }, s: { padding: sizes.s }, m: { padding: sizes.m }, l: { padding: sizes.l }, xl: { padding: sizes.xl }, xxl: { padding: sizes.xxl }, full: { padding: sizes.full }, }, top: { auto: { paddingTop: sizes.auto }, xxs: { paddingTop: sizes.xxs }, xs: { paddingTop: sizes.xs }, s: { paddingTop: sizes.s }, m: { paddingTop: sizes.m }, l: { paddingTop: sizes.l }, xl: { paddingTop: sizes.xl }, xxl: { paddingTop: sizes.xxl }, full: { paddingTop: sizes.full }, }, bottom: { auto: { paddingBottom: sizes.auto }, xxs: { paddingBottom: sizes.xxs }, xs: { paddingBottom: sizes.xs }, s: { paddingBottom: sizes.s }, m: { paddingBottom: sizes.m }, l: { paddingBottom: sizes.l }, xl: { paddingBottom: sizes.xl }, xxl: { paddingBottom: sizes.xxl }, full: { paddingBottom: sizes.full }, }, left: { auto: { paddingLeft: sizes.auto }, xxs: { paddingLeft: sizes.xxs }, xs: { paddingLeft: sizes.xs }, s: { paddingLeft: sizes.s }, m: { paddingLeft: sizes.m }, l: { paddingLeft: sizes.l }, xl: { paddingLeft: sizes.xl }, xxl: { paddingLeft: sizes.xxl }, full: { paddingLeft: sizes.full }, }, right: { auto: { paddingRight: sizes.auto }, xxs: { paddingRight: sizes.xxs }, xs: { paddingRight: sizes.xs }, s: { paddingRight: sizes.s }, m: { paddingRight: sizes.m }, l: { paddingRight: sizes.l }, xl: { paddingRight: sizes.xl }, xxl: { paddingRight: sizes.xxl }, full: { paddingRight: sizes.full }, }, vertical: { auto: { paddingVertical: sizes.auto }, xxs: { paddingVertical: sizes.xxs }, xs: { paddingVertical: sizes.xs }, s: { paddingVertical: sizes.s }, m: { paddingVertical: sizes.m }, l: { paddingVertical: sizes.l }, xl: { paddingVertical: sizes.xl }, xxl: { paddingVertical: sizes.xxl }, full: { paddingVertical: sizes.full }, }, horizontal: { auto: { paddingHorizontal: sizes.auto }, xxs: { paddingHorizontal: sizes.xxs }, xs: { paddingHorizontal: sizes.xs }, s: { paddingHorizontal: sizes.s }, m: { paddingHorizontal: sizes.m }, l: { paddingHorizontal: sizes.l }, xl: { paddingHorizontal: sizes.xl }, xxl: { paddingHorizontal: sizes.xxl }, full: { paddingHorizontal: sizes.full }, }, },};
And will be use like that:
<View style={theme.spacings.margin.bottom.xxl} />
It looks like not DRY code and maybe there is a way to optimize this code to more readable and maintanable code?