I am trying to create a React component that has a render-prop with a generic type. To make the component easier to use I also want to supply a default value for the render-prop. The code works as expected. However, when I type-check the code I get the following warning about conflicts between the PropTypes and Typescript specifications. Can anyone explain why I'm getting this error or how to fix it?
src/test.tsx:19:3 - error TS2322: Type '{ ({ data }: TChildProps<TData>): JSX.Element; propTypes: { data: PropTypes.Validator<NonNullable<PropTypes.InferProps<{ id: PropTypes.Validator<string>; }>>>; }; }' is not assignable to type 'FunctionComponent<TChildProps<V>>'.
The types of 'propTypes.data' are incompatible between these types.
Type 'Validator<NonNullable<InferProps<{ id: Validator<string>; }>>>' is not assignable to type 'null extends V ? Validator<V | (V & null) | undefined> : undefined extends V ? Validator<V | (V & undefined) | null> : Validator<V>'.
19 Child = DefaultChild,
Here is a simplified version of my code that produces the error:
import PropTypes from "prop-types";
export interface TData {
id: string;
}
export interface TChildProps<V extends TData> {
data: V;
}
export interface TParentProps<V extends TData> {
data: V;
Child?: React.ComponentType<TChildProps<V>>; // Causes PropTypes validation error.
}
export const Parent = <V extends TData>({
data,
Child = DefaultChild,
}: TParentProps<V>) => {
return <Child data={data}></Child>;
};
export const DefaultChild = ({ data }: TChildProps<TData>) => {
return <p>{data.id}</p>;
};
DefaultChild.propTypes = {
data: PropTypes.shape({
id: PropTypes.string.isRequired,
}).isRequired,
};
Update
It's not a perfect solution, but it is possible to disable the error by explicitly setting the type of DefaultChild.propTypes to object:
DefaultChild.propTypes = {
data: PropTypes.shape({
id: PropTypes.string.isRequired,
}).isRequired,
} as object;
In your code, the problem is how the
propTypesofDefaultChildare defined, TypeScript's PropTypes validator has different behavior based on the type of the generic it receives, so here is the conflict.you can have a look at this article it introduces how to use
PropTypes.InferProps