问题
I have a function that looks at the provided children and if a particular element type is found, it adds some properties to it automatically.
The function is called like this:
render () {
const { children, name, className } = this.props;
return (
<div className={className}>
{this.enrichRadioElements(children, name)}
</div>
)
}
and it is implemented like this:
enrichRadioElements = (children: Array<any>, name: string) => (
React.Children.map(children, child => {
if (!React.isValidElement(child)) {
return child;
}
//@ts-ignore
if (child.props.children) {
child = React.cloneElement(child, {
//@ts-ignore
children: this.enrichRadioElements(child.props.children, name)
});
}
if (child.type === Radio) {
return React.cloneElement(child, {
onChange: this.handleFieldChange,
selectedValue: this.state.selectedValue,
name: name
})
}
else {
return child;
}
})
)
The two //@ts-ignore
comments are what I'm trying to get rid of by writing code that will satisfy typescript. If I remove the first one, the error message I see is this:
Property 'children' does not exist on type '{}'.(ts-2339)
How can I properly modify my code so I can remove the //@ts-ignore
comments? I did go to the definition of child.props and I found this:
interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
type: T;
props: P;
key: Key | null;
}
which looks to have a 'props' of type any (if I'm reading it correctly), but typescript doesn't recognize the children property.
回答1:
The problem is a couple of things. I started by changing children: Array<any>
to children: React.ReactNode
. You already have a check in there to narrow the type from ReactNode to ReactElement. The trick was 1. using the generic type arguments in isValidElement
and 2. using a new variable with a type assignment on it elementType
rather than dealing with and mutating the child
argument. EnrichedChildren
may need to be updated to match your use case.
interface EnrichedChildren {
onChange(): void
selectedValue: string
name: string
children?: React.ReactNode
}
enrichRadioElements = (children: React.ReactNode, name: string): any =>
React.Children.map(children, child => {
if (!React.isValidElement<EnrichedChildren>(child)) {
return child
}
let elementChild: React.ReactElement<EnrichedChildren> = child
if (child.props.children) {
elementChild = React.cloneElement<EnrichedChildren>(elementChild, {
children: this.enrichRadioElements(elementChild.props.children, name),
})
}
if (elementChild.type === 'Radio') {
return React.cloneElement(elementChild, {
onChange: () => {},
selectedValue: 'value',
name: name,
})
} else {
return elementChild
}
})
来源:https://stackoverflow.com/questions/55464194/how-to-define-typescript-for-react-children-map