【问题标题】:How to type a styled component without losing any prop with Typescript?如何使用 Typescript 在不丢失任何道具的情况下键入样式组件?
【发布时间】:2019-08-05 20:04:53
【问题描述】:

我是样式化组件的新手,我希望能够正确输入样式化组件,这样当我传递“vs code”道具时,我可以自动检测我拥有的所有道具,而不仅仅是主题中的那个或者我可以用接口放置的那些。

我在其他answer 中看到的那样,如果不使用 HOC,有什么办法吗?是否有可能获得一个通用的道具来使用,而不必像示例中那样在样式的每个属性中定义?

app.theme.ts

export const theme = {
  palette: {
    primaryColor: '#FF5018',
    secondaryColor: '#252729',
    tertiaryColor: '#1A1C1E',
    textColor: 'white',
  },
};

export type Theme = typeof theme;

navigation-bar.styled.component.ts

export const NavigationBarStyled = styled.div`
  grid-area: navigation-bar-item;
  padding-left: 2rem;
  display: flex;
  align-items: center;
  color: ${({ theme }) => theme.palette.primaryColor};
  background-color: ${({ theme }) => theme.palette.primaryColor};
`;

提前致谢, 最好的

【问题讨论】:

    标签: reactjs typescript styled-components


    【解决方案1】:

    出于某种原因(可能是由于styled-components 的打字稿定义的编写方式),如果您删除其中一个嵌套级别,Theme 的打字工作。这个 sn-p 类型检查对我来说没有错误(v4),即打字稿知道primaryColorstring

    const theme = {
      primaryColor: '#FF5018',
      secondaryColor: '#252729',
      tertiaryColor: '#1A1C1E',
      textColor: 'white',
    };
    
    type Theme = typeof theme;
    
    type Props = Theme & {
      // ... other keys
    }
    
    const NavigationBarStyled = styled.div<Props>`
      grid-area: navigation-bar-item;
      padding-left: 2rem;
      display: flex;
      align-items: center;
      color: ${props => props.primaryColor};
      background-color: ${props => props.primaryColor};
    `;
    

    【讨论】:

    • 嗨@Huy-Nguyen,谢谢你的回答,但是有了这个道具的实现,你不会失去关于样式化组件或反应的其他属性吗?因为您减少了仅具有主题属性或您输入的自定义属性的可能性?
    • 还有... 是否可以一次调用附件来使用它们?提前致谢!
    【解决方案2】:

    这可以像@Huy-Nguyen 所说的那样解决,但实际上,您会丢失样式组件的属性,或者您必须多次定义相同的属性。

    所以最好的选择就是 Styled-Components 网站所说的(定义主题界面):

    主题.ts

    export default interface ThemeInterface {
      primaryColor: string;
      primaryColorInverted: string;
    }
    

    styled-components.ts

    import * as styledComponents from "styled-components";
    
    import ThemeInterface from "./theme";
    
    const {
      default: styled,
      css,
      createGlobalStyle,
      keyframes,
      ThemeProvider
    } = styledComponents as styledComponents.ThemedStyledComponentsModule<ThemeInterface>;
    
    export { css, createGlobalStyle, keyframes, ThemeProvider };
    export default styled;
    

    然后,你使用它:

    import styled from 'app/styled-components';
    
    // theme is now fully typed
    const Title = styled.h1`
      color: ${props => props.theme.primaryColor};
    `;
    

    只需传递链接:https://www.styled-components.com/docs/api#define-a-theme-interface

    非常感谢大家。

    【讨论】:

      【解决方案3】:

      我们采用了不同的方法。
      注意:带有 React Native 的 Styled Components v5

      • 定义您的主题类型。

        // MyTheme.ts
        
        export type MyTheme = {
          colors: {
            primary: string;
            background: string;
          };
        };
        
      • 在您的主题上使用类型。

        // themes.ts
        
        export const LightTheme: MyTheme = {
          colors: {
            primary: 'white',
            background: 'white',
          },
        };
        
        export const DarkTheme: MyTheme = {
          colors: {
            primary: 'grey',
            background: 'black',
          },
        };
        
      • 使用 declaration merging 将 MyTheme 类型“合并”到 Styled Components 默认主题中。

        // styled.d.ts
        
        import 'styled-components';
        import { MyTheme } from '../src/themes/MyTheme';
        
        declare module 'styled-components' {
          // eslint-disable-next-line @typescript-eslint/no-empty-interface
          export interface DefaultTheme extends MyTheme {}
        }
        

      好的,很酷。 theme 属性输入正确。
      组件本身呢?

      • 将您的特定组件道具包装在 StyledProps 类型中。

        import { StyledProps } from 'styled-components';
        import styled from 'styled-components/native';
        
        type MyViewProps = StyledProps<{
          backgroundColor?: string;
          isAlert?: boolean;
        }>;
        
        const MyView = styled.View(
          (props: MyViewProps) => `
            background-color: ${props.backgroundColor || props.theme.colors.background};
            color: ${props.isAlert ? red : props.theme.colors.primary}
          `,
        );
        

      在此示例中,props.backgroundColorprops.theme.colors.background 都将自动完成。当您更新 MyTheme 类型或特定组件类型时,它应该可以正常工作。 ?

      【讨论】:

      • 我发誓这种方法一直对我有用。但是我正在处理的当前项目中的某些内容有所不同,我在props 上看到的所有类型都是any。我唯一不同的是我使用的是StyledComponentsThemeProvider。你有什么想法为什么我只是在道具上得到任何东西?
      【解决方案4】:

      我不知道这是否是最好的方法。但我找到了如下解决方案。

      // theme.ts
      const theme = {
        colors: {
           ...
        }
      };
      export type themeTypes = typeof theme;
      export default theme;
      
      
      // styled.d.ts ( in root folder )
      import 'styled-components'
      import { themeTypes } from '@/styles/theme'
      
      declare module 'styled-components' {
        // eslint-disable-next-line @typescript-eslint/no-empty-interface
        export interface DefaultTheme extends themeTypes {}
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-26
        • 2021-05-10
        • 2021-11-01
        • 2020-01-07
        • 2021-08-15
        • 2019-05-11
        • 2023-01-11
        相关资源
        最近更新 更多