If you know how to fix the issue, make a pull request instead.
@types/react package and had problems.Definitions by: in index.d.ts) so they can respond.I have the following component:
interface LayoutProps {
children: React.ReactNode;
}
type LayoutComponent = React.ComponentType<LayoutProps>;
interface RootProps {
Layout?: LayoutComponent;
}
class Root extends React.Component<RootProps> {
static defaultProps: Pick<RootProps, 'Layout'> = {
Layout: ({ children }: { children: React.ReactNode }) => <>{children}</>
};
render() {
const { Layout, children } = this.props;
return (
<Layout> // JSX element type 'Layout' does not have any construct or call signatures.
{children}
</Layout>
);
}
}
ReactDOM.render(<Root>Foobar</Root>, document.getElementById('mount-node'));
typescript does not pick up the fact that there is a defaultProp for Layout which I thought it would due to the new LibraryManagedAttributes mapped type.
I am using @types/[email protected] and typescript 3.0.3.
Typescript complains about Layout not being callable when I thought that the prop would be mapped from defaultProps
I have strictNullChecks set to true.
If I add this code, then it is fine:
render() {
const { Layout, children } = this.props;
if (!Layout) {
return null;
}
return <Layout>{children}</Layout>;
}
Library managed attributes allows the resolution to happen outside the component. If you have a default prop for Layout then this should be how you structure the code:
interface RootProps {
Layout: LayoutComponent
}
class Root extends React.Component<RootProps> {
static defaultProps = {
Layout: ({ children }: { children: React.ReactNode }) => <>{children}</>
}
render() {
return <this.props.Layout /> // this is guaranteed to be defined based on RootProps
}
}
const myRoot = <Root /> // LibraryManagedAttributes allows you to render Root in JSX
// without needing to pass in an attribute called 'Layout'
@ferdaber provided a clear solution. can we close this ?
Thanks for the solution @ferdaber. Is there an alternative option that would allow the use of an optional prop in the interface?
I have a component that is exposed via through a public API and defining a required prop in the interface seems confusing when the prop does not need to be included in the component instance.
Currently we are getting around this by using optional props in the interface and a ! anywhere we use a prop which has a default value but that doesn't feel ideal either.
The interface itself is used for internal consumption by the component itself. If you want to get the "apparent" or "allowable" props for the component (i.e. for external consumption), maybe for reuse, you can do this:
interface Props = { /* ... */ }
class MyComponent extends React.Component<Props> { /* ... */ }
type AllowableMyComponentProps = JSX.LibraryManagedAttributes<typeof MyComponent, Props>
This will take any static defaultProps as well as propTypes of MyComponent and resolve it against Props with the same algorithm that determines allowable JSX attributes to be given.
Most helpful comment
The interface itself is used for internal consumption by the component itself. If you want to get the "apparent" or "allowable" props for the component (i.e. for external consumption), maybe for reuse, you can do this:
This will take any static
defaultPropsas well aspropTypesofMyComponentand resolve it againstPropswith the same algorithm that determines allowable JSX attributes to be given.