I have tried 2 different ways to do this based on some google searches. I'm trying to setup typing for a custom theme in typescript expo reactive native project. I've setup a declaration ts file and added it to my includes in tsconfig. Here is my setup. Hoping someone out there has went through similar issues and knows how to fix this.
I have a themes folder with the following files that I export out and then import into a index theme file.
themes/
colors
sizes
spacing
index
Here is the index file importing from the above 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;
then I have my declaration file which I tried 2 ways one manually adding all the props and the other using 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",
]
}
Then this is how I'm using this in my tsx app 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;
`;
Don't set DefaultTheme
in your themes/index.ts
. It's already used and is just an empty object.
Update your themes/index.ts
to this:
import { colors } from "./colors";
import { sizes } from "./sizes";
import { spacing, lineHeights } from "./spacing";
const theme = {
colors,
sizes,
spacing,
lineHeights,
};
export default theme;
Update your types/theme.d.ts
this:
import "styled-components"
import theme from "./src/themes";
type ThemeInterface = typeof theme
declare module "styled-components" {
// eslint-disable-next-line @typescript-eslint/no-empty-interface (this is only necessary if you ur eslint complains. Since it should be and Interface and not a Type.)
interface DefaultTheme extends ThemeInterface {}
}
And you should be gucci.