cloneElement:Type没有与Partial <p>&amp;类型相同的属性。属性

时间:2018-05-11 16:58:25

标签: reactjs typescript definitelytyped

在类似下面的代码中,我得到了Type { foo: number } has no properties in common with type 'Partial<Child> & Attributes'来调用cloneElement的第二个参数,我不明白为什么......在我看来Partial<Child>获得了正确形状的道具,但TypeScript不同意。

以下是https://github.com/DefinitelyTyped/DefinitelyTyped

中的库版本
"@types/react": "16.3.14",
"@types/react-dom": "16.0.5",

以下是示例:

import * as React from "react";
interface Props {
  foo: number;
}
class Child extends React.Component<Props> {
    public render(): React.ReactNode {
        return <span>{this.props.foo}</span>;
    }
}
class Parent extends React.Component<Props> {
    public render(): React.ReactNode {
        return React.Children.map(this.props.children, (child: JSX.Element) => this.cloneChild(child));
    }

    public cloneChild(child: React.ReactElement<Child>): React.ReactElement<Child> {
        const newProps = {
            foo: this.props.foo,
        };
        return React.cloneElement<Child>(child, newProps);
    }
}

这是一个错误,还是我错过了什么?

1 个答案:

答案 0 :(得分:3)

ReactElementcloneElement的类型参数表示道具的类型而不是组件,所以你可能想要这样:

public cloneChild(child: React.ReactElement<Props>): React.ReactElement<Props> {
    const newProps = {
        foo: this.props.foo,
    };
    return React.cloneElement<Props>(child, newProps);
}

或等同地

public cloneChild(child: React.ReactElement<Props>) {
    const newProps = {
        foo: this.props.foo,
    };
    return React.cloneElement(child, newProps);
}

此外,还有错误的类型转换(child: JSX.Element)childReact.Children.map的类型为ReactChild(归结为ReactElement<any> | string | number),并转换为JSX.Element(== ReactElement<any>) ,你没有考虑可能的字符串或数字儿童。由于cloneElementstring子项上的number失败,因此当您包含例如文本元素时,当前代码会产生运行时错误:<Parent>x<Child/></Parent>

要在不进行强制转换的情况下摆脱类型错误,您可以像这样检查stringnumber

public render() {
    return React.Children.map(this.props.children, (child) =>
      typeof child === 'number' || typeof child === 'string'
      ? child
      : this.cloneChild(child)
    );
}