我正在嘗試為我的樣式元件實作一種可選的樣式覆蓋。
目前我有這個:
这是一个函数,将会将我改变的样式与主题中的默认样式合并。
const mergeComponentTheme = <T extends object>(mode: ThemeMode, defaultTheme: T, overridingTheme?: CustomComponentStyle<T>): T => { return Object.keys(defaultTheme).reduce<T>((previousValue, currentValue) => { const property = currentValue as keyof T; const themeMode = mode as keyof typeof overridingTheme; const value = (overridingTheme && overridingTheme[themeMode][property]) || defaultTheme[property]; return { ...previousValue, [currentValue]: value }; }, {} as T); };
这是我目前的使用方式。
const Button = styled.button<CustomStyled<ButtonTheme>>` ${({ theme, customStyle }) => { const componentStyle = mergeComponentTheme<ButtonTheme>(theme.mode, theme.current.button, customStyle); return css` background-color: ${componentStyle.backgroundColor}; color: ${componentStyle.foregroundColor}; padding: ${componentStyle.padding}; margin: ${componentStyle.margin}; border-radius: ${componentStyle.borderRadius}; filter: drop-shadow(0 0 2px ${componentStyle.dropShadowColor}); transition: all 0.2s ease-in-out; &:hover { background-color: ${componentStyle.backgroundColorHover}; cursor: pointer; } `; }} `;
这些是示例中使用的所有类型。
type CustomStyled<T> = { customStyle?: CustomComponentStyle<T>; }; type CustomComponentStyle<T> = { light?: Partial<T>; dark?: Partial<T>; }; enum ThemeMode { LIGHT = 'light', DARK = 'dark', } interface ButtonTheme extends GenericTheme { borderRadius: Radius; } type GenericTheme = { backgroundColor: Color; foregroundColor: Color; backgroundColorHover: Color; foregroundColorHover: Color; dropShadowColor: Color; margin: Space; padding: Space; };
有沒有更簡潔的方法來做到這一點。我願意聽取建議。
不過,幾乎忘了問題的標題。所以我的主要問題是,如果我從themeMode
常數中刪除這部分as keyof typeof overridingTheme;
,overridingTheme[themeMode]
會說即使在檢查之後它可能是未定義的。
P粉7344867182023-09-11 00:50:08
嘗試:
const value = (overridingTheme?.[themeMode]?.[property]) ?? defaultTheme[property];