我有这个简单的通用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]属性'source'在类型'IntrinsicAttributes&IGenComponentProps&{children ?: ReactNode; }'。
[ts]属性'opacity'在类型'IntrinsicAttributes&IGenComponentProps&{children ?: ReactNode; }'。
或:
<GenComponent
ComponentName={View}
testId="left-container"
accessibilityHint="left-container"
>
{ someContent }
</GenComponent>
[ts]属性'accessibilityHint'在类型'IntrinsicAttributes&IGenComponentProps&{children ?: ReactNode; }'。
答案 0 :(得分:1)
如果您希望在不枚举那些名称的情况下允许使用任何名称的属性,则可以执行以下操作:
interface IGenComponentProps {
ComponentName: string;
testId?: string;
[key: string]: any;
}
请注意,您将对此进行有限的类型检查。您的IDE基本上会强制ComponentName存在并且是字符串,如果testId存在,则它是字符串。其他所有东西都是免费的,但至少是允许的。
答案 1 :(得分:0)
您可以放松组件的props接口,但是所有GenComponent都会丢失其所有子类型的信息。
相反,我将使用通用的高阶组件:
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 & ImageProps
我在这种模式下找到了good article。