score:0
Here is a working version.
Props needs to extend PropsWithChildren<any>
, like so:
import * as React from "react";
import { render } from "@testing-library/react";
function renderContainer<Props extends React.PropsWithChildren<any>>(
//function renderContainer<Props>(
Container: React.ComponentType<Props>,
props?: Props
) {
return render(
<Container {...props}>
<div>Child</div>
</Container>
);
}
type CustomComponentProps = {
children?: React.ReactNode;
prop1: number;
prop2?: string;
};
const CustomComponent = ({ prop1, prop2, children }: CustomComponentProps) => (
<div>{children}</div>
);
// Expected behavior:
renderContainer(CustomComponent, { prop1: 1 }); // ok
renderContainer(CustomComponent, { prop1: 1, prop2: "string" }); // ok
renderContainer(CustomComponent, { prop3: 3 }); // error
/* Argument of type '({ prop1, prop2, children }: CustomComponentProps) => JSX.Element' is not assignable to parameter of type 'ComponentType<{ prop3: number; }>'.
Type '({ prop1, prop2, children }: CustomComponentProps) => JSX.Element' is not assignable to type 'FunctionComponent<{ prop3: number; }>'.
Types of parameters '__0' and 'props' are incompatible.
Property 'prop1' is missing in type 'PropsWithChildren<{ prop3: number; }>' but required in type 'CustomComponentProps'.ts(2345) /*
If you want the error on the props instead of CustomComponent:
import * as React from "react";
import { render } from "@testing-library/react";
function renderContainer<Props extends React.PropsWithChildren<any>>(
//function renderContainer<Props>(
Container: React.ComponentType<Props>,
props?: Props
) {
return render(
<Container {...props}>
<div>Child</div>
</Container>
);
}
type CustomComponentProps = {
children?: React.ReactNode;
prop1: number;
prop2?: string;
};
const CustomComponent: React.ComponentType<CustomComponentProps> = ({ prop1, prop2, children }) => (
<div>{children}</div>
);
// Expected behavior:
renderContainer(CustomComponent, { prop1: 1 }); // ok
renderContainer(CustomComponent, { prop1: 1, prop2: "string" }); // ok
renderContainer(CustomComponent, { prop3: 3 }); // error
/* Argument of type '{ prop3: number; }' is not assignable to parameter of type 'CustomComponentProps'.
Object literal may only specify known properties, but 'prop3' does not exist in type 'CustomComponentProps'. Did you mean to write 'prop1'? /*
score:1
Actually, the easier way to resolve this problem is to think the other way around, and setting the generic in renderContainer
as the Component type it self, instead of the props.
type ReactComponent = JSXElementConstructor<any>;
type CustomComponentProps = {
children?: React.ReactNode;
prop1: number;
prop2?: string;
};
const CustomComponent = ({ prop1, prop2, children }: CustomComponentProps) => (
<div>{children}</div>
);
declare function renderContainer<T extends ReactComponent>(container: T, props: React.ComponentProps<T>): React.ReactNode
renderContainer(CustomComponent, { prop1: 1 }); // ok
renderContainer(CustomComponent, { prop1: 1, prop2: "string" }); // ok
renderContainer(CustomComponent, { prop3: 3 }); // error
This way is more natural, because you are defining what will be the component first and then the props will be inferred by TypeScript, you don't even have to specifically pass any generic into the function.
Source: stackoverflow.com
Related Query
- How can a function correctly accept a React component and its props as arguments in TypeScript and render this component?
- How do I test a React component that calls a function on its parent, which changes props on the component?
- How can I return a React Component from a function and render it onClick?
- How to make React functional component recreate callback function and read updated props
- How can I pass props from one component to another using Link and router in react
- React functional component test file unable to update state value and call its props function
- How can I refactor my React component to accept an array of errors and shows an error message if error.show = true for any one of those errors
- How to correctly annotate component props that can accept Component or string as html tag?
- How can I type a generic component that takes as one of its arguments a function that returns an AxiosResponse?
- How can i pass HTML inside React Hook Function and display inside my component secure?
- How to set React component state and props from browser
- how to access vairables outside of map function in js and jsx in a React component
- React Typescript how send props and use it in child component
- How can I spread props to a React component that uses exact props when using Flow?
- What does forwardRef by a component in React dev tools mean and how can I use it?
- how to change image src using props with styled component and react
- React testing - How can I mock or inject data in the store to be provided as props to component
- How can I initialize Redux state for React component on its creation?
- How to test with jest and typescript with types a basic react function component
- How can I get React styleguidist to install correctly and get past the peer Dependency issues with react-simple-code-editor: React 16 & 17?
- How to pass arguments to function in functional component in React
- How can we write a click handler for a Stateless Function Component in React JS
- How does React update a component and its children after a state change?
- How can I use useEffect in React to run some code only when the component first mounts, and some other code whenever an event occurs (repeatedly)?
- How can I make sure a React parent component loads data before its child component mounts?
- How to make my component re render after updating props from selector in react and redux-saga?
- How to pass dynamic props to a React component that accepts a union of objects as its type?
- How React Testing Library can assert children props and Redux store updates?
- how to set react parent component state by a async function and then pass this state to child as props?
- How to pass a function as props when both Parent and Child component also a functional component?
More Query from same tag
- show 'no solution found' when array length is 0
- Tesing the store file in Redux using Jest and Enzyme
- How do I store JWT and send them with every request using react
- React Hook - Converting from class to hooks - Ternary Operator
- How to set a type for a React Compnent being passed in as a prop
- How to add fonts to create-react-app based projects?
- React function await not working. Executing at the same time
- Infinite looping due to setState in componentDidUpdate method?
- Map() Menu Items. How scope selected menu item?
- created a pop up modal with no error but it isnt showing the image/description
- how to use map and boolean variables inside paths? (can't return the attributes using routers)
- How to read data from axios response through module.exports?
- How to change text color in TextField?
- How to set scrollbar at the bottom by default?
- How to to style dropdown menu in material-ui Nativeselect?
- Is there a way to check for any state changes made by a user in React?
- How to color label on radio-button on react-materialize
- How to change the status if I clicked on a close button in react js
- My html template carousel not working on react
- I can't get a value out of Redux store in App component
- How to style Antd component
- convert the circle border onto clickable function
- get the value from select option inside <li> react
- What does {...props} in this React Component mean?
- Mobx observable and componentDidUpdate() not behaving as expected when passing props [Typescript React]
- Confused about the usage of useReducer assigned to onClick event
- Tabulator image enlarge on click
- Await for an element not to appear
- Best way to render HTML emails in React app
- New item in the list disappears