After conducting some research online, I have experimented with two different methods to achieve typing for a custom theme in a React Native project using TypeScript and Expo. I created a declaration ts file and included it in my tsconfig. Below is an overview of my setup, and I'm hopeful that someone who has encountered similar challenges can provide guidance on resolving this issue.
In my themes folder, I have various files which I export and then import into an index theme file as follows:
themes/
colors
sizes
spacing
index
The index file imports from the aforementioned theme files:
import { DefaultTheme } from "styled-components/native";
import { colors } from "./colors";
import { sizes } from "./sizes";
import { spacing, lineHeights } from "./spacing";
const theme: DefaultTheme = {
colors,
sizes,
spacing,
lineHeights,
};
export default theme;
Furthermore, I attempted two approaches in creating my declaration file – one involving manual addition of all props and the other utilizing 'typeof'.
types/theme.d.ts
import {} from "styled-components";
import theme from "../themes";
declare module "styled-components" {
type Theme = typeof theme;
export interface DefaultTheme extends Theme {}
}
// Manually adding the props.
// import { DefaultTheme } from "styled-components/native";
// declare module "styled-components" {
// export interface DefaultTheme {
// bg: {
// primary: string;
// secondary: string;
// };
// sizes: stringp[];
// lineHeights: {
// title: string;
// copy: string;
// };
// spacing: string[];
// }
// }
tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"baseUrl": ".",
"paths": {
"*": ["types/*"]
},
},
"include": ["./src", "./types"],
"exclude": [
"node_modules",
"**/*.test.ts",
"**/*.test.tsx",
]
}
Finally, here is how I am implementing this in my app's tsx file:
App.tsx
import React from "react";
import styled, { ThemeProvider } from "styled-components/native";
import { Text, StatusBar } from "react-native";
import theme from "./src/themes";
export default function App() {
return (
<ThemeProvider theme={theme}>
<Container>
<Text>some text</Text>
<StatusBar />
</Container>
</ThemeProvider>
);
}
const Container = styled.View`
flex: 1;
background-color: ${({ theme }) => theme.colors.bg.primary};
align-items: center;
justify-content: center;
`;