在Typescript React App中指定特定的道具并接受常规的HTML道具

Ser*_*ert 4 javascript typescript reactjs react-props

我有一个React Wrapper组件,它接受一些道具,但将所有其他道具转发给子组件(尤其是对诸如className,id等本机道具的相关事件)。

但是,当我通过本地道具时,打字稿抱怨。查看错误消息:

TS2339:类型'IntrinsicAttributes和IntrinsicClassAttributes <包装器>&只读<{子代?:ReactNode; }>和Readonly <WrapperProps>”。

如何获得带有特定道具的组件,该组件也接受本机道具(接受任何道具并放弃类型检查)?

我的代码如下所示:

interface WrapperProps extends JSX.IntrinsicAttributes {
  callback?: Function
}

export class Wrapper extends React.Component<WrapperProps>{
  render() {
    const { callback, children, ...rest } = this.props;
    return <div {...rest}>
      {children}
    </div>;
  }
}

export const Test = () => {
  return <Wrapper className="test">Hi there</Wrapper>
}
Run Code Online (Sandbox Code Playgroud)

仅供参考:我在这里找到了类似的问题,但是答案基本上是放弃类型检查,我想避免这种情况:链接到SO-Question

Ada*_*per 9

看一下ComponentPropsComponentPropsWithRef、 和ComponentPropsWithoutRef- 这将接受通用输入,可以是"div""button"或任何其他组件。它将包括反应特定的道具,例如className

import React, {
  forwardRef,
  ComponentPropsWithoutRef,
  ComponentProps,
  ComponentPropsWithRef
} from "react";

const ExampleDivComponent = forwardRef<
  HTMLDivElement,
  ComponentPropsWithoutRef<"div">
>(({ children, ...props }, ref) => {
  return (
    <div {...props} ref={ref}>
      {children}
    </div>
  );
});

<ExampleDivComponent
  className=""
  style={{ background: "green" }}
  tabIndex={0}
  onTouchStart={() => alert("touched")}
/>;

const ExampleButtonComponent: React.FC<ComponentProps<"button">> = ({
  children,
  ...props
}) => {
  return <button {...props}>{children}</button>;
};

<ExampleButtonComponent onClick={() => alert("clicked")} />;

Run Code Online (Sandbox Code Playgroud)


Tit*_*mir 8

我们可以看看divprops的定义方式:

interface IntrinsicElements {
    div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
}
Run Code Online (Sandbox Code Playgroud)

如果将其React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>用作基本类型,则将具有的所有属性div。由于DetailedHTMLProps刚刚添加refReact.HTMLAttributes<HTMLDivElement>我们可以将其用作获取所有div属性的基本接口:

interface WrapperProps extends React.HTMLAttributes<HTMLDivElement> {
  callback?: Function
}

export class Wrapper extends React.Component<WrapperProps>{
  render() {
    const { callback, children, ...rest } = this.props;
    return <div {...rest}>
      {children}
    </div>;
  }
}

export const Test = () => {
  return <Wrapper className="test">Hi there</Wrapper> // works now
}
Run Code Online (Sandbox Code Playgroud)


sch*_*pet 8

JSX.IntrinsicElements 有此信息,例如

const FooButton: React.FC<JSX.IntrinsicElements['button']> = props => (
  <button {...props} className={`foo ${props.className}`} />
)

// alternative...
const FooButton: React.FC<React.PropsWithoutRef<
  JSX.IntrinsicElements['button']
>> = props => <button {...props} className={`foo ${props.className}`} />
Run Code Online (Sandbox Code Playgroud)

在react-typescript-cheatsheet项目中发现了这一点。