cloneElement: Type 与 Partial<P> & Attributes 类型没有共同的属性
cloneElement: Type has no properties in common with type Partial<P> & Attributes
在类似于以下的代码中,我得到 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);
}
}
这是一个错误,还是我遗漏了什么?
ReactElement
和 cloneElement
的类型参数表示 props 的类型而不是组件的类型,所以你可能是这样想的:
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)
。 React.Children.map
中 child
的类型是 ReactChild
(归结为 ReactElement<any> | string | number
,)并转换为 JSX.Element
(== ReactElement<any>
) ,您没有考虑可能的字符串或数字 children。由于 cloneElement
在 string
或 number
children 上失败,如果您包含例如文本元素,当前代码会给出运行时错误:<Parent>x<Child/></Parent>
.
要在不强制转换的情况下消除类型错误,您可以像这样检查 string
和 number
:
public render() {
return React.Children.map(this.props.children, (child) =>
typeof child === 'number' || typeof child === 'string'
? child
: this.cloneChild(child)
);
}
在类似于以下的代码中,我得到 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);
}
}
这是一个错误,还是我遗漏了什么?
ReactElement
和 cloneElement
的类型参数表示 props 的类型而不是组件的类型,所以你可能是这样想的:
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)
。 React.Children.map
中 child
的类型是 ReactChild
(归结为 ReactElement<any> | string | number
,)并转换为 JSX.Element
(== ReactElement<any>
) ,您没有考虑可能的字符串或数字 children。由于 cloneElement
在 string
或 number
children 上失败,如果您包含例如文本元素,当前代码会给出运行时错误:<Parent>x<Child/></Parent>
.
要在不强制转换的情况下消除类型错误,您可以像这样检查 string
和 number
:
public render() {
return React.Children.map(this.props.children, (child) =>
typeof child === 'number' || typeof child === 'string'
? child
: this.cloneChild(child)
);
}