查看以下代码示例
// Component.tsx file
import React from "react";
export const Component = ({ title, subTitle }: Props) => {
return (
<div>
<h1>{title}</h1>
<p>{subTitle}</p>
</div>
);
};
// Props declared here
type Props = {
title: string;
subTitle: string;
};
// App.tsx file
import { Component } from "./Component";
import "./styles.css";
export default function App() {
const componentData: any = {
title: "Hello",
subTitle: "Hello from comp"
};
return (
<div className="App">
// TS does not show an error here even though randomProp is not described on Component's Props
<Component {...componentData} randomProp="string" />
</div>
);
}
正如你所看到的,在App.tsx
的第5行,componentData
对象被输入为any,在App.tsx
的第11行,我使用spread操作符将该对象作为另一个组件的 prop 发送。
如果我这样做,TS将中止检查发送的其余 prop ,如您所见,randomProp="string"
不会抛出错误。
如果我从第5行的对象中删除:any
类型,那么TS会在Component
的属性中将randomProp="string"
标记为不存在(我预计第5行的:any
也会发生这种情况)。
以下示例不使用结构化,TS以这种方式显示错误
// App.tsx file
import { Component } from "./Component";
import "./styles.css";
export default function App() {
const componentData: any = {
title: "Hello",
subTitle: "Hello from comp"
};
return (
<div className="App">
<Component
title={componentData.title}
subTitle={componetData.subTitle}
// TS shows an error here!
randomProp="string"
/>
</div>
);
}
如需了解更多信息:
请看这个CodeSandbox:https://codesandbox.io/s/elated-worker-td2g0u?file=/src/App.tsx .
还有这个https://codesandbox.io/s/shy-monad-ygkloq?file=/src/App.tsx
这是一个有意的行为还是一个bug?这在下面是如何工作的?
1条答案
按热度按时间x759pob21#
any
类型显式地意味着关闭类型检查,它往往是“传染性的”或“传染性的”,因为将any
与其他类型组合通常会导致any
。尽可能避免any
。不过,如果你需要使用它,你应该了解更多细节,了解它如何与其他类型交互,以及它何时“接管”其他类型,何时不接管。
由于
componendData
的类型为any
,编译器将允许您使用任何键对其进行索引,并且结果属性的类型也将为any
:如果您使用
any
类型的值作为属性值来创建对象文本,则只有那些属性将具有any
类型;它不会“感染”整个对象:因此,如果你试图给
Props
类型的变量赋值,编译器会欣然接受any
属性(即使它无法验证它们,这正是any
的意义所在),但它会捕获多余的属性,因为对象文本知道它们的存在:现在让我们比较一下当你把一个
any
类型的值spread到一个对象常量中时会发生什么:从概念上讲,扩展将导致类似于扩展对象类型与对象常量其余部分类型的交集(对于键已知的扩展,编译器将尝试更准确地表示被覆盖的属性,但对于泛型或其他未知键类型,它使用交集)。
any
与任何其他类型的交集就是any
:所以
objSpread
的值现在是any
类型,编译器已经完全忘记了randomProp
,这意味着如果你给Props
类型的值赋值,编译器不会看到任何多余的属性,因为any
没有任何“多余”属性:所以,如果你把
any
扩展到一个对象字面量中,它会“感染”整个对象,变成any
。但是如果你把any
类型的属性单独添加到一个对象中,any
类型将被限制在这些属性中。Playground代码链接