Reputation: 1121
So I'm trying to nest a TypeScript React component within another, but it complains about types. It would seem it wants me to add all of my props into the parent interface?
Is there a way of doing this without having to have all my types listed in the child component interface, but then also having to add the types to the parent component interface?
Note: I am using Styled Components in the example below
interface IField {
children: React.ReactNode
}
export function Field({ children, htmlFor, label, required, ...props }: IField) {
return (
<FormField {...props}>
<Label htmlFor={htmlFor} label={label} required={required}/>
{children}
</FormField>
)
}
interface ILabel {
htmlFor: string
label: string
required?: boolean
}
export function Label({ htmlFor, label, required }: ILabel) {
return (
<FormLabel htmlFor={htmlFor}>
{label}
{required && (
<Required />
)}
</FormLabel>
)
}
Error I get:
Type '{}' is missing the following properties from type 'ILabel': htmlFor, label
Thanks for any help in advance!
Upvotes: 1
Views: 5186
Reputation: 6089
To avoid adding the properties from the child interface back to the parent component interface you can use extends
(see TypeScript inheritance documentation).
After that, you can pass the props
from the parent to the child component by using {...props}
deconstructor on the child component.
And finally, if you are using TypeScript might as well use React.FunctionComponent
typing to avoid having to manually type children
.
You can check at this simplified working example:
https://stackblitz.com/edit/react-stackoverflow-60228406
I tried to adapt your snippet below...
import React from 'react';
interface IField extends ILabel {
}
export const Field: React.FunctionComponent<IField> = (props) => {
return (
<FormField>
<Label {...props} />
{props.children}
</FormField>
)
};
interface ILabel {
htmlFor: string
label: string
required?: boolean
}
export const Label: React.FunctionComponent<ILabel> = (props) => {
return (
<FormLabel htmlFor={props.htmlFor}>
{props.label}
{props.required && (<Required />)}
</FormLabel>
)
};
Upvotes: 1