web-dev-qa-db-ja.com

TypeScriptで特定の小道具を指定して一般的なHTML小道具を受け入れるReact App

私はReactラッパーコンポーネントを持っています。これはいくつかの小道具を受け入れますが、他のすべてを子コンポーネントに転送します(特に、className、idなどのネイティブ小道具に関連します)。

しかし、ネイティブの小道具を渡すと、TypeScriptは文句を言います。エラーメッセージを参照してください。

TS2339:プロパティ 'className'はタイプ 'IntrinsicAttributes&IntrinsicClassAttributes <Wrapper>&Readonly <{children?:ReactNode; }>&読み取り専用<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>
}

参考:ここで同様の質問を見つけましたが、答えは基本的に型チェックをあきらめ、避けたいと思います: SOへのリンク-質問

6
Sergej Herbert

div小道具がどのように定義されているかを見ることができます。

interface IntrinsicElements {
    div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
}

基本タイプとしてReact.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>を使用すると、divのすべてのプロパティが得られます。 DetailedHTMLPropsrefReact.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
}

私の同僚はそれを理解しました。より広い可視性のためにここで共有する:

interface ComponentPropTypes = {
  elementName?: keyof JSX.IntrinsicElements; // list of all native DOM components
  ...
}


// Function component
function Component({
  elementName: Component = 'div',
  ...rest,
  // React.HTMLAttributes<HTMLOrSVGElement>) provides all possible native DOM attributes
}: ComponentPropTypes & React.HTMLAttributes<HTMLOrSVGElement>)): JSX.Element {
  return <Component {...rest} />;
}

// Class component
class Component extends React.Component<ComponentPropTypes & React.HTMLAttributes<HTMLOrSVGElement>> {
  render() {
    const {
      elementName: Component,
      ...rest,
    } = this.props;
    return <Component {...rest} />
  }
}
0
webbower