For my React-Native project, I'm trying to get as much autocomplete and type validation as I can. One of the challenges is to configure the types for the stylesheet library I use.
An extended stylesheet looks like this:
const styles = createStyles({
variable1: 100,
variable2: "10rem",
header: {
width: "100%",
height: 40,
alignContent: "center",
flex: "$flexAll",
margin: "$gapMD"
}
})
When I define the styles, every style value should not only accept its original type, but also a string, function etc.
When the library is done processing the stylesheet, the result is a regular React-Native stylesheet. Therefore the result of the function should contain the same properties as the input of the function, but the properties should be mapped to the original style types.
For example flex should be a number, not a number | string | function | etc.
Here is what I've got so far:
import { ImageStyle, TextStyle, ViewStyle } from "react-native"
import EStyleSheet from "react-native-extended-stylesheet"
type Function<K> = () => K
type AllStyles = ImageStyle & TextStyle & ViewStyle
type StyleSet<T> = { [P in keyof T]: AllStyles }
type EValue<T> = T | string & {}
type EVariable<K> = EValue<K> | Function<EValue<K>>
type EStyle<T> = { [P in keyof T]: EVariable<T[P]> }
type EAnyStyle = EStyle<ImageStyle> | EStyle<TextStyle> | EStyle<ViewStyle>
type EStyleSet<T> = { [P in keyof T]: number | string | EAnyStyle | EStyleSet<T> }
export const createStyles = <T>(styles: EStyleSet<T>) =>
EStyleSheet.create(styles) as StyleSet<T>
Unfortunately autocomplete doesn't work completely and I feel that my definitions are becoming a bit too complex. The result type also isn't completely correct.
I really hope that there is a TypeScript wizard out there that can help me to get this working.
I've set up a Sandbox that can be used to test some of the types:
https://codesandbox.io/s/typescript-style-mania-h62cv