【问题标题】:Typescript: Defining undeclared props for generic React component打字稿:为通用 React 组件定义未声明的道具
【发布时间】:2019-02-27 20:18:26
【问题描述】:

我有一个简单的通用 React 组件,我并不总是知道我将使用哪种元素类型或道具,也不想为每个潜在道具设置一个接口。

使用 TS v2.9。

在这种情况下,我使用的是 React Native 而不是 React 的事实不应该是相关的。

import React, { StatelessComponent as SC } from "react";

interface IGenComponentProps {    
  /**
   * Component type
   */
  ComponentName: string;

  /**
   * Test Id used for automation testing
   */
  testId?: string;

  /**
   * I'd like to define this here to supress TS errors I'm getting
   */         
  remainderProps?: any;
}

const GenComponent:SC<IGenComponentProps> = ({ComponentName, testId, children, ...remainderProps}) => {

  return (
    <ComponentName id={testId} {...remainderProps}>
      {children}
    </ComponentName>
  )
}

export default GenComponent;

这很好用,符合预期,但在使用组件时出现 TS 错误:

   <GenComponent 
      ComponentName={Image}
      testId="test-image"
      source={{uri: 'someImageSrc'}}
      opacity={0.1}
    />

[ts] 类型'IntrinsicAttributes & IGenComponentProps & { children?: ReactNode; 上不存在属性'source' }'。

[ts] 属性“不透明度”不存在于类型“IntrinsicAttributes & IGenComponentProps & { children?: ReactNode; }'。

或:

   <GenComponent
      ComponentName={View}
      testId="left-container"
      accessibilityHint="left-container"
    >
      { someContent }
   </GenComponent>

[ts] 属性 'accessibilityHint' 不存在于类型'IntrinsicAttributes & IGenComponentProps & { children?: ReactNode; }'。

【问题讨论】:

    标签: javascript reactjs typescript react-native typescript-typings


    【解决方案1】:

    如果您希望能够在不枚举这些名称的情况下允许具有任何名称的属性,您可以执行以下操作:

    interface IGenComponentProps {    
      ComponentName: string;
      testId?: string;
      [key: string]: any;
    }
    

    请注意,您将对此进行有限的类型检查。您的 IDE 将基本上强制 ComponentName 存在并且是一个字符串,并且如果 testId 存在它是一个字符串。其他任何东西都是免费的,但至少是允许的。

    【讨论】:

    • 这适用于我需要它做的事情 - 谢谢。我对使用这个 GenComponent 在组件内部传递的道具进行了严格的类型检查。我很欣赏解释+警告:)
    【解决方案2】:

    您可以放宽组件的 props 接口,但是您的所有 GenComponents 将丢失所有子组件的类型信息。

    相反,我会使用通用的高阶组件:

    interface ITest {
      id: string;
    }
    
    function withId<T>(WrappedComponent) {
      return class extends Component<ITest & T> {
        public render() {
          return <WrappedComponent id={this.props.id} {...this.props} />;
        }
      };
    }
    
    const TestableImage = withId<ImageProps>(Image);
    
    const ExampleUsage = props =>
      <View>
        <TestableImage
        id="required"
        source={{ uri: "also required" }}
        // Plus any other optional image image props
        />
      </View>;
    

    在这种情况下,您的包装组件将具有 props 接口 ITest &amp; ImageProps

    我在这个图案上找到了good article

    【讨论】:

      猜你喜欢
      • 2023-01-15
      • 1970-01-01
      • 2019-05-22
      • 1970-01-01
      • 2021-07-11
      • 2021-02-12
      • 1970-01-01
      • 2017-02-16
      • 2021-11-10
      相关资源
      最近更新 更多