【问题标题】:Default props with wrapped Styled Component in TypescriptTypescript 中带有包装样式组件的默认道具
【发布时间】:2020-05-01 18:44:45
【问题描述】:

我正在开发一个包含几个默认道具的组件,我想将它们传递给样式化组件。这是我目前所在的位置:

import React, { FC } from "react";
import styled from "styled-components";
// Icon SVG code
import Icons from "./icons";

const icons = ["add", "subtract"];

interface Props {
  className?: string;
  icon: typeof icons[number];
  size?: number;
}

const Wrapper = styled.div<Omit<Props, "icon">>(({ size }) => ({
  width: size,
  height: size
}));

const Icon: FC<Props> = ({ className, icon, size = 24 }) => (
  <Wrapper className={className} size={size}>
    <Icons icon={icon} />
  </Wrapper>
);

对于顶级组件 API,size 应该是一个可选属性,因为它有一个默认值 (24)。但是,size 应该标记为 Wrapper 样式组件的必需值,因为如果开发人员没有提供默认值,React 将确保始终应用默认值。

我想知道是否有人对设计模式提出建议来解决这个问题,而不必多次重写相同接口的变体。我还在使用所有依赖项的最新版本,包括 TS、React 和 Styled Components。

非常感谢!

【问题讨论】:

  • 您想要解决的一般问题是什么?您的问题有一个简单的解决方案。什么样的场景需要重复解决方案?
  • 感谢@aron 的回复。我应该提供更多信息。我上面写的代码示例实际上不起作用。 Typescript 抱怨是理所当然的,因为 sizeIcon 上的可选道具,但在 Wrapper 上是必需的。我知道这完全没问题,因为 React 将应用默认大小值24,但我不知道如何让 TS 意识到这一点。这说明清楚了吗?

标签: reactjs typescript styled-components


【解决方案1】:

如果我理解正确,这种类型可能会有所帮助

type RequireKey<T, Key> = { [K in keyof Required<T>]: K extends Key ? NonNullable<T[K]> : T[K] }

要创建 Props 的修改版本,其中大小不再是未定义的,您可以这样做

// The original Props that is Icon's external interface
interface Props {
  className?: string;
  icon: typeof icons[number];
  size?: number;
}

// Props with "size" made mandatory
type RequireSize = RequireKey<Props, "size">

// type RequireSize = {
//   className: string | undefined;
//   icon: string;
//   size: number; <- no longer optional!
// }

如果您现在在 Wrapper 中使用 RequireSize 而不是 Props,那么“size”的类型将缩小为 number 而不是 number | undefined

const Wrapper = styled.div<Omit<RequireSize, "icon">>(({ size }) => ({
  width: size,
  height: size
}));

// Use Props as before
const Icon: FC<Props> = ({ className, icon, size = 24 }) => (
  <Wrapper className={className} size={size}>
    <Icons icon={icon} />
  </Wrapper>
);

【讨论】:

    猜你喜欢
    • 2020-07-12
    • 2020-01-24
    • 2019-05-20
    • 2019-12-27
    • 2019-08-20
    • 2020-01-25
    • 2020-12-21
    • 2021-03-30
    • 2017-05-20
    相关资源
    最近更新 更多