【问题标题】:How to make React and Typescript to allow either base set of properties or an extended one如何使 React 和 Typescript 允许使用基本属性集或扩展属性集
【发布时间】:2021-12-09 10:42:42
【问题描述】:

我有一个 React 包装器组件,它根据“变体”道具呈现特定组件。有基本组件和其他两个扩展基本组件的道具。联合类型不起作用。这是包装器组件的代码:

type Props = 
  | ({ variant: "first" } & FirstComponentProps) }
  | ({ variant: "second" } & SecondComponentProps)
  | BaseComponentProps);

export default function WrapperComponent(props: Props) {
  switch (props.variant) {
    case "first":
      return <FirstComponent {...props} />
    case "second":
      return <SecondComponent {...props} />
    default:
      return <BaseComponent {...props} />
  }
}

这些组件的类型:

type BaseComponentProps = { propA: string; }
type FirstComponentProps = { propB: string } & BaseComponentProps
type SecondComponentProps = { propC: string } & BaseComponentProps

以及如何使用这个包装组件:

<WrapperComponent variant="first" propA="value" propB="value" />
<WrapperComponent variant="second" propA="value" propC="value" />
<WrapperComponent propA="value" />

这应该会触发打字稿警告:

<WrapperComponent propA="value" propB="value" />

如何正确键入包装器组件的 props 以便它只允许正确的 props 组合?

谢谢!

【问题讨论】:

  • 改用接口

标签: javascript reactjs typescript


【解决方案1】:

有一个棘手的解决方案:

type Props =
  | ({ variant: "first" } & FirstComponentProps)
  | ({ variant: "second" } & SecondComponentProps)
  | ({ variant?: void } & { [key in Exclude<keyof (FirstComponentProps & SecondComponentProps), keyof BaseComponentProps>]?: void } & BaseComponentProps);

游乐场结果here

它是如何工作的?

由于Type Compatibility,您的BaseComponentProps允许其他变体的属性,但它被视为BaseComponentProps,因此没有触发任何警告。

让变体的道具为void 可以警告你不应该放置变体的道具,因为该类型是void

或者使用泛型组件:

type WrapperComponentProps<T extends 'first' | 'second' | '_base' = '_base'> =
  T extends '_base'
  ? { variant?: void } & BaseComponentProps
  : { variant: T } & ({
    'first': FirstComponentProps,
    'second': SecondComponentProps,
  }[Exclude<T, '_base'>]);

export default function WrapperComponent<T extends 'first' | 'second' | '_base' = '_base'>(props: WrapperComponentProps<T>) {
  switch (props.variant) {
    case "first":
      return <FirstComponent {...props} />
    case "second":
      return <SecondComponent {...props} />
    default:
      return <BaseComponent {...props} />
  }
}

游乐场结果here

这将根据条件限制道具类型(默认为BaseComponentProps)。

【讨论】:

  • 谢谢!效果很好!
猜你喜欢
  • 2019-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 2020-11-07
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多