简体   繁体   English

使用样式组件“as”prop与typescript

[英]Using styled components “as” prop with typescript

I'm currently building a pattern library in which I've built a Button component using React and styled-components . 我目前正在构建一个模式库,其中我使用Reactstyled-components构建了一个Button styled-components Based on the Button component, I want all my Link s component to look exactly the same and receive exactly the same props. 基于Button组件,我希望我的所有Link组件看起来完全相同,并获得完全相同的道具。 For that purpose, I'm using the as prop from styled-components , which allows me to use that already built element as another tag or component. 为此,我使用styled-components as prop,它允许我将已构建的元素用作另一个标记或组件。

Button Component 按钮组件

import * as React from 'react'
import { ButtonBorderAnimation } from './ButtonAnimation'
import { ButtonProps, ButtonVariant } from './Button.types'
import { ButtonBase, LeftIcon, RightIcon } from './Button.styled'

function Button({
  variant = ButtonVariant.Filled,
  children,
  leftIcon = null,
  rightIcon = null,
  ...props
}: ButtonProps): JSX.Element {
  return (
    <ButtonBase variant={variant} {...props}>
      {variant !== ButtonVariant.Ghost ? (
        <ButtonBorderAnimation {...props} />
      ) : null}
      {leftIcon ? <LeftIcon>{leftIcon}</LeftIcon> : null}
      {children}
      {rightIcon ? <RightIcon>{rightIcon}</RightIcon> : null}
    </ButtonBase>
  )
}

export default Button

Button Types 按钮类型

export interface ButtonProps {
  children: React.ReactNode
  variant?: 'filled' | 'outlined' | 'ghost'
  size?: 'small' | 'regular'
  underlinedOnHover?: boolean
  leftIcon?: React.ReactNode
  rightIcon?: React.ReactNode
  inverse?: boolean
}

export enum ButtonVariant {
  Filled = 'filled',
  Outlined = 'outlined',
  Ghost = 'ghost',
}

export enum ButtonSize {
  Small = 'small',
  Regular = 'regular',
}

Link Component 链接组件

import * as React from 'react'
import Button from '../Button/Button'
import { Link as LinkRouter } from 'react-router-dom'
import { LinkProps } from './Link.types'

function Link({ to, ...props }: LinkProps): JSX.Element {
  return <Button to={to} as={LinkRouter} {...props} />
}

export default Link

Link Types 链接类型

import { ButtonProps } from '../Button/Button.types'
import { LinkProps } from 'react-router-dom'

type RouterLinkWithButtonProps = ButtonProps & LinkProps

export interface LinkProps extends RouterLinkWithButtonProps {}

When I do the above, this problem comes us... 当我做上述事情时,我们遇到了这个问题......

Property 'to' does not exist on type 'IntrinsicAttributes & ButtonProps'.

...which makes sense because button doesn't have the prop to which is required for the Link component from react-router-dom . ......这是有道理的,因为按钮没有道具to这是需要的Link从组件react-router-dom

How will you approach something like this? 你将如何处理这样的事情? Where when using the Button the to prop shouldn't even be in the type and when using the Link the to should be required. 当使用Button to支柱甚至不应该在类型中,并且在使用Link to应该要求。

Uses 用途

<Button>Hello</Button>
<Link to="/somewhere">Hello</Link>

This should work. 这应该工作。

function Link(_props: LinkProps): JSX.Element {
  const props = { as: LinkRouter, ..._props };
  return <Button {...props} />
}

Note that TypeScript applies strict object literal assignment checks which can be loosened by assigning an object literal to a variable beforehand instead of directly passing it as, for example, an function argument, which is consistent with the React component props assignment behavior. 请注意,TypeScript应用严格的对象文字赋值检查 ,可以通过事先将对象文字分配给变量而不是直接将其作为例如函数参数传递来放松,该函数参数与React组件props赋值行为一致。

declare function foo(arg: { a: number }): void;

foo({ to: '', a: 1 }); // error

const arg = { to: '', a: 1 };
foo(arg); // no error

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM