使用 'as' styled-components 的 polymorphic prop with typescript

Using 'as' polymorphic prop of styled-components with typescript

我正在尝试实现 Typography React 组件。
正如您在下面看到的,我将 variant 作为输入道具并将其用作 VariantsMap 对象的索引以获取相应的 html 标签名称。

然后我使用 styled-components 'as' polymorphic prop 将其呈现为选定的 html 标记。

但我一直收到此错误:
No overload matches this call. Overload 1 of 2, '(props: Omit<Omit<Pick<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "key" | keyof HTMLAttributes<...>> & { ...; } & { ...; }, never> & Partial<...>, "theme"> & { ...; } & { ...; }): ReactElement<...>', gave the following error. Type 'string' is not assignable to type 'undefined'.

我在@types/styled-component中发现'as' props可以是'never | undefined',而我的variantsMap returns字符串类型
但我真的想将这个 'as' 道具与我的变体特定 html 标签选择功能一起使用。

有什么办法可以解决这个问题吗?

const variantMap = {
  h1: 'h1',
  h2: 'h2',
  h3: 'h3',
  h4: 'h4',
  h5: 'h5',
  h6: 'h6',
  subheading1: 'h6',
  subheading2: 'h6',
  body1: 'p',
  body2: 'p',
};

export const Typography = ({ variant : string }) => { 

      const selectedComponent = variantMap[variant];

      return (<TypographyRoot
        as={selectedComponent}
        variant={variant}
        {...props}
      >
        {children}
      </TypographyRoot>);
}

首先,export const Typography = ({ variant : string }) => {} 是无效语法。

您刚刚将 destructured variant 的名称更改为 string。您没有提供类型。

即使使用像此处 export const Typography = ({ variant }:{variant: string}) => {} 这样的有效 string 类型,您仍然出错的原因是 variantMap 期望作为键 h1 | 'h2' |'h3' ... 键而 string 更宽。 我敢打赌您不想将 foo 字符串分配给 variant 属性.

为了修复它,您只需要使 variantMap 不可变并对 variantMap:

应用适当的约束
import React from 'react'
import styled from "styled-components";

const Div = styled.div`
  color: red;
`;

const VariantMap = {
  h1: 'h1',
  h2: 'h2',
  h3: 'h3',
  h4: 'h4',
  h5: 'h5',
  h6: 'h6',
  subheading1: 'h6',
  subheading2: 'h6',
  body1: 'p',
  body2: 'p',
} as const;

type Props = {
  variant: keyof typeof VariantMap
}
export const Typography = ({ variant }: Props) => {

  const selectedComponent = VariantMap[variant];

  return <Div
    as={selectedComponent}
  />
}

现在styled-component很开心。

Playground


Making the map immutable saved me. Can you explain why not making the map immutable makes Typescript complain?

如果没有 as constVariantMap 的所有值都被推断为 string 而不是文字 "h1", "h2"。这又会影响 selectedComponent,因为此 const 表示 VariantMap 的值。我的意思是 selectedComponent 变成了一个普通的 string 而不是字符串文字,而 as 属性 期望严格的字符串文字 h1, h2, h3, ...