This document explains the TypeScript types and interfaces used in the theme system of the Fynd Commerce App.
The theme system uses comprehensive TypeScript types to ensure:
- Type Safety: Compile-time validation of theme properties
- IntelliSense: Complete autocomplete support
- Documentation: Self-documenting code with clear type definitions
- Maintainability: Easy refactoring and updates
The main theme interface that defines the complete theme structure.
// src/app/types/theme.type.ts
export type CustomTheme = {
color: ColorPalette;
typography: Typography;
spacing: Spacing;
radius: Radius;
layout: Layout;
};Defines all available colors in the theme system.
export type ColorPalette = Record<CustomColorPallete, string>;
export type CustomColorPallete =
| 'primaryColor'
| 'secondaryColor'
| 'accentColor'
| 'linkColor'
| 'bgColor'
| 'pageBackground'
| 'themeAccent'
| 'textHeading'
| 'textBody'
| 'textLabel'
| 'textSecondary'
| 'buttonPrimary'
| 'buttonSecondary'
| 'buttonLink'
| 'saleBadgeBackground'
| 'saleBadgeText'
| 'saleDiscountText'
| 'saleTimer'
| 'headerBackground'
| 'headerNav'
| 'headerIcon'
| 'footerBackground'
| 'footerBottomBackground'
| 'footerHeadingText'
| 'footerBodyText'
| 'footerIcon'
| 'dialogBackground'
| 'overlay'
| 'dividerStokes'
| 'highlightColor'
| 'successBackground'
| 'successText'
| 'errorBackground'
| 'errorText'
| 'informationBackground'
| 'informationText'
| 'themeAccentD1'
| 'themeAccentD2'
| 'themeAccentD3'
| 'themeAccentD4'
| 'themeAccentD5'
| 'themeAccentL1'
| 'themeAccentL2'
| 'themeAccentL3'
| 'themeAccentL4'
| 'themeAccentL5'
| 'buttonPrimaryL1'
| 'buttonPrimaryL3'
| 'buttonLinkL1'
| 'buttonLinkL2'
| 'white'
| 'dustyGray'
| 'gray'
| 'mako'
| 'mako2'
| 'black'
| 'iron'
| 'lightGray';Defines typography-related properties including fonts, sizes, weights, and spacing.
export type Typography = {
fontFamily: Record<string, string>;
fontSize: FontSize;
fontWeight: FontWeight;
lineHeight: LineHeight;
letterSpacing: LetterSpacing;
};
export type FontSize = {
xs: number;
sm: number;
base: number;
md: number;
lg: number;
xl: number;
xxl: number;
heading: number;
};
export type FontWeight = {
regular: TextStyle['fontWeight'];
medium: TextStyle['fontWeight'];
bold: TextStyle['fontWeight'];
};
export type LineHeight = {
xs: number;
sm: number;
base: number;
md: number;
lg: number;
xl: number;
xxl: number;
heading: number;
};
export type LetterSpacing = {
xs: number;
sm: number;
base: number;
md: number;
lg: number;
xl: number;
xxl: number;
heading: number;
};Defines the spacing scale used throughout the app.
export type Spacing = {
none: number;
xs: number;
sm: number;
md: number;
base: number;
lg: number;
xl: number;
xxl: number;
xxxl: number;
};Defines border radius values for different UI elements.
export type Radius = {
button: number;
badge: number;
image: number;
};Defines layout-specific properties.
export type Layout = {
productImgAspectRatio: number;
};Defines the structure of theme configuration received from the server.
export type ThemeProviderMergedGlobalConfig = {
palette: {
general_setting?: {
button?: {
button_primary?: string;
button_link?: string;
button_primary_l1?: string;
button_primary_l3?: string;
button_secondary?: string;
button_link_l1?: string;
button_link_l2?: string;
};
theme?: {
theme_accent?: string;
theme_accent_d1?: string;
theme_accent_d2?: string;
theme_accent_d3?: string;
theme_accent_d4?: string;
theme_accent_d5?: string;
theme_accent_l1?: string;
theme_accent_l2?: string;
theme_accent_l3?: string;
theme_accent_l4?: string;
theme_accent_l5?: string;
page_background?: string;
};
page_background?: string;
header?: {
header_background?: string;
header_nav?: string;
header_icon?: string;
};
footer?: {
footer_background?: string;
footer_bottom_background?: string;
footer_heading_text?: string;
footer_body_text?: string;
footer_icon?: string;
};
sale_discount?: {
sale_badge_background?: string;
sale_badge_text?: string;
sale_discount_text?: string;
sale_timer?: string;
};
text?: {
text_heading?: string;
text_body?: string;
text_label?: string;
text_secondary?: string;
};
shape?: {
product_img_aspect_ratio?: number;
};
overlay_popup?: {
dialog_backgroung?: string;
overlay?: string;
};
};
advance_setting?: {
overlay_popup?: {
dialog_backgroung?: string;
overlay?: string;
};
user_alerts?: {
success_background?: string;
error_background?: string;
info_background?: string;
success_text?: string;
error_text?: string;
info_text?: string;
};
divider_stroke_highlight?: {
divider_strokes?: string;
};
highlight?: {
highlight_color?: string;
};
};
};
button_border_radius: string;
badge_border_radius: string;
image_border_radius: string;
};// Extend color palette with custom colors
export type ExtendedColorPalette = ColorPalette & {
customBrand: string;
customAccent: string;
customNeutral: string;
customSuccess: string;
customWarning: string;
customError: string;
};
// Create semantic color types
export type SemanticColors = {
success: {
primary: string;
light: string;
dark: string;
};
warning: {
primary: string;
light: string;
dark: string;
};
error: {
primary: string;
light: string;
dark: string;
};
info: {
primary: string;
light: string;
dark: string;
};
};// Extend font family types
export type ExtendedFontFamily = {
regular: string;
medium: string;
bold: string;
display: string;
mono: string;
serif: string;
customBrand: string;
};
// Extend font size types
export type ExtendedFontSize = FontSize & {
display: number;
hero: number;
micro: number;
nano: number;
};
// Extend font weight types
export type ExtendedFontWeight = FontWeight & {
light: TextStyle['fontWeight'];
semibold: TextStyle['fontWeight'];
extrabold: TextStyle['fontWeight'];
black: TextStyle['fontWeight'];
};// Extend spacing types
export type ExtendedSpacing = Spacing & {
micro: number;
nano: number;
huge: number;
massive: number;
};
// Component-specific spacing
export type ComponentSpacing = {
button: {
small: number;
medium: number;
large: number;
};
card: {
compact: number;
comfortable: number;
spacious: number;
};
form: {
fieldGap: number;
sectionGap: number;
groupGap: number;
};
};// Extend layout types
export type ExtendedLayout = Layout & {
containerMaxWidth: number;
sidebarWidth: number;
headerHeight: number;
footerHeight: number;
borderRadius: {
small: number;
medium: number;
large: number;
round: number;
};
shadows: {
small: ShadowStyle;
medium: ShadowStyle;
large: ShadowStyle;
};
};
// Shadow style type
export type ShadowStyle = {
shadowColor: string;
shadowOffset: {
width: number;
height: number;
};
shadowOpacity: number;
shadowRadius: number;
elevation?: number;
};// Extract specific theme properties
export type ThemeColors = CustomTheme['color'];
export type ThemeTypography = CustomTheme['typography'];
export type ThemeSpacing = CustomTheme['spacing'];
export type ThemeRadius = CustomTheme['radius'];
export type ThemeLayout = CustomTheme['layout'];
// Create partial theme types
export type PartialTheme = Partial<CustomTheme>;
export type PartialColors = Partial<ThemeColors>;
export type PartialTypography = Partial<ThemeTypography>;
// Create theme override types
export type ThemeOverride = {
color?: Partial<ThemeColors>;
typography?: Partial<ThemeTypography>;
spacing?: Partial<ThemeSpacing>;
radius?: Partial<ThemeRadius>;
layout?: Partial<ThemeLayout>;
};// Theme props for components
export type ThemedComponentProps = {
theme: CustomTheme;
variant?: 'primary' | 'secondary' | 'outline';
size?: 'small' | 'medium' | 'large';
disabled?: boolean;
};
// Style function types
export type StyleFunction<T> = (theme: CustomTheme, props?: any) => T;
export type ThemedStyleFunction<T> = (theme: CustomTheme) => T;
// Theme hook return types
export type ThemeHookReturn = {
theme: CustomTheme;
colors: ThemeColors;
typography: ThemeTypography;
spacing: ThemeSpacing;
radius: ThemeRadius;
layout: ThemeLayout;
};// Theme validation types
export type ThemeValidator = {
isValid: boolean;
errors: string[];
warnings: string[];
};
// Theme validation function
export type ValidateTheme = (theme: CustomTheme) => ThemeValidator;
// Required theme properties
export type RequiredThemeProperties = {
color: Required<Pick<ThemeColors, 'primaryColor' | 'textBody' | 'bgColor'>>;
typography: Required<Pick<ThemeTypography, 'fontSize' | 'fontWeight'>>;
spacing: Required<Pick<ThemeSpacing, 'base' | 'md' | 'lg'>>;
};// Conditional theme properties
export type ConditionalTheme<T extends keyof CustomTheme> =
CustomTheme[T] extends object ? CustomTheme[T] : never;
// Theme property paths
export type ThemePath =
| 'color.primaryColor'
| 'color.textBody'
| 'typography.fontSize.base'
| 'spacing.md'
| 'radius.button';
// Extract theme value by path
export type ThemeValue<T extends ThemePath> = T extends `color.${infer C}`
? ThemeColors[C & keyof ThemeColors]
: T extends `typography.${infer T}`
? ThemeTypography[T & keyof ThemeTypography]
: T extends `spacing.${infer S}`
? ThemeSpacing[S & keyof ThemeSpacing]
: T extends `radius.${infer R}`
? ThemeRadius[R & keyof ThemeRadius]
: never;// Create theme property getters
export type ThemeGetters = {
[K in keyof CustomTheme]: () => CustomTheme[K];
};
// Create theme property setters
export type ThemeSetters = {
[K in keyof CustomTheme]: (value: CustomTheme[K]) => void;
};
// Create theme property updaters
export type ThemeUpdaters = {
[K in keyof CustomTheme]: (
updater: (value: CustomTheme[K]) => CustomTheme[K],
) => void;
};// Create color variant types
export type ColorVariant = 'light' | 'dark' | 'lighter' | 'darker';
export type ColorWithVariant<
C extends keyof ThemeColors,
V extends ColorVariant,
> = `${C}${Capitalize<V>}`;
// Example: 'primaryColorLight', 'primaryColorDark', etc.
export type ColorVariants = ColorWithVariant<'primaryColor', ColorVariant>;
// Create size variant types
export type SizeVariant = 'small' | 'medium' | 'large';
export type SizeWithVariant<
S extends keyof ThemeSpacing,
V extends SizeVariant,
> = `${S}${Capitalize<V>}`;
// Example: 'spacingSmall', 'spacingMedium', etc.
export type SizeVariants = SizeWithVariant<'spacing', SizeVariant>;// Type guard for valid theme
export const isValidTheme = (theme: any): theme is CustomTheme => {
return (
theme &&
typeof theme === 'object' &&
'color' in theme &&
'typography' in theme &&
'spacing' in theme &&
'radius' in theme &&
'layout' in theme
);
};
// Type guard for valid color palette
export const isValidColorPalette = (colors: any): colors is ColorPalette => {
return (
colors &&
typeof colors === 'object' &&
'primaryColor' in colors &&
'textBody' in colors &&
'bgColor' in colors
);
};
// Type guard for valid typography
export const isValidTypography = (
typography: any,
): typography is Typography => {
return (
typography &&
typeof typography === 'object' &&
'fontSize' in typography &&
'fontWeight' in typography &&
'lineHeight' in typography
);
};// Check if color exists
export const hasColor = (
theme: CustomTheme,
color: string,
): color is keyof ColorPalette => {
return color in theme.color;
};
// Check if font size exists
export const hasFontSize = (
theme: CustomTheme,
size: string,
): size is keyof FontSize => {
return size in theme.typography.fontSize;
};
// Check if spacing exists
export const hasSpacing = (
theme: CustomTheme,
space: string,
): space is keyof Spacing => {
return space in theme.spacing;
};- Always use strict typing for theme properties
- Avoid
anytypes in theme definitions - Use union types for variant properties
- Design types to be easily extensible
- Use generic types for reusable patterns
- Create utility types for common operations
- Add JSDoc comments to complex types
- Use descriptive type names
- Provide examples in type comments
- Use efficient type operations
- Avoid deeply nested conditional types
- Use mapped types sparingly
- Keep types organized and modular
- Use consistent naming conventions
- Separate concerns in type definitions
- Advanced Type Inference: More sophisticated type inference for theme properties
- Runtime Type Validation: Runtime validation based on TypeScript types
- Theme Schema Generation: Automatic schema generation from types
- Type-Safe Theme Builders: Builder patterns for creating themes
This documentation covers the TypeScript types used in the theme system. For more specific implementation details, refer to the other theme documentation sections.