具有样式组件的TypeScript

art*_*ras 5 typescript reactjs styled-components

这里是TypeScript新手。我有一个下面的组件styled-components,希望将其转换为TypeScript

import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'


const propTypes = {
  name: PropTypes.string.isRequired // https://material.io/tools/icons/?style=baseline
}

const Icon = styled(({name, className, ...props}) => <i className={`material-icons ${className}`} {...props}>{name}</i>)`
  font-size: ${props => props.theme.sizeLarger};
`

Icon.propTypes = propTypes

export default Icon
Run Code Online (Sandbox Code Playgroud)

我知道我可以代替我propTypesinterface

interface Props {
  name: string
}
Run Code Online (Sandbox Code Playgroud)

但是,TypeScript抱怨我没有className声明。问题是,理想情况下,我希望将interface用作开发人员可以提供的道具规范,而不必声明诸如classNametheme由注入的道具styled-components

如何正确地将此组件转换为TypeScript?

Gol*_*Jer 6

这是使用带有 React Native 的 Styled Components v5 的综合方法,它也适用于普通的 React。如果您不使用主题,则可以跳至StyledProps底部的部分。

  • 定义您的主题类型。

    // MyTheme.ts
    
    export type MyTheme = {
      colors: {
        primary: string;
        background: string;
      };
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 在您的主题上使用类型。

    // themes.ts
    
    export const LightTheme: MyTheme = {
      colors: {
        primary: 'white',
        background: 'white',
      },
    };
    
    export const DarkTheme: MyTheme = {
      colors: {
        primary: 'grey',
        background: 'black',
      },
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用声明合并将 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 {}
    }
    
    Run Code Online (Sandbox Code Playgroud)

嗯不错。该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}
      `,
    );
    
    Run Code Online (Sandbox Code Playgroud)

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

组件自动完成

他们自动完成


tor*_*kel 5

import React from "react";
import styled from "styled-components";

interface Props {
  name: string;
  className?: string;
}

const NonStyledIcon: React.SFC<Props> = ({ name, className, ...props }) => (
  <i className={`material-icons ${className}`} {...props}>
    {name}
  </i>
);

const Icon = styled(NonStyledIcon)`
  font-size: ${props => props.theme.sizeLarger};
`;

export default Icon;

Run Code Online (Sandbox Code Playgroud)

根据样式化组件TypeScript docs:在定义组件时,您需要在Props界面中将className标记为可选