如何通用键入React组件道具和扩展通用道具类型

时间:2020-02-06 00:30:27

标签: reactjs typescript

我有一个将元素类型参数化的组件。我想输入此组件,以便您可以指定元素的类型并将道具限制为该类型。

interface IProps<T> extends T {
  elementName: string,
}

class Foo<T> extends React.Component<IProps<T>, {}> {
  render() {
    const { elementName, ...props } = this.props;
    return React.createElement(elementName, {
        ...props,
    });
  }
}

例如,当道具的类型为href时,AnchorHTMLAttributes是有效的道具,而当道具的类型为HTMLAttributes时,则不是有效的道具。

// Ok
<Foo<AnchorHTMLAttributes<AnchorHTMLElement>> href="foo.com"/>

// Type checker error because `href` is not an attribute of a div
<Foo<HTMLAttributes<HTMLDivElement>> href="foo.com"/>

这可能吗?如果可能,怎么办?

1 个答案:

答案 0 :(得分:1)

您想要的类型是:

<td className="dataTableCell" style="width: 200px;">
      <span>$</span>
      <div style="float: right">99999</div>
</td>

React.InputHTMLAttributes<HTMLInputElement> 都替换为其他类型的标签。

看起来最通用的约束是:

Input

然后,您可以将该类型与可以为您提供React.HTMLAttributes<HTMLElement> 的内容进行合并。有了约束和elementName,您将得到:

elementName

或作为类组件:

function Foo<T extends React.HTMLAttributes<HTMLElement>>(
  props: T & { elementName: string },
) {
  const { elementName, ...otherProps } = props
  return React.createElement(elementName, otherProps)
}

用法像您期望的那样工作,尽管您必须提供class Foo<T extends React.HTMLAttributes<HTMLElement>> extends React.Component< T & { elementName: string } > { render() { const { elementName, ...otherProps } = this.props return React.createElement(elementName, otherProps) } }

elementName

Working Playground