为何TypeScript中{}允许非空值,而FC<{}>却不接受任意Props?
React TypeScript 中空接口{}作为组件Props的矛盾解析
问题背景
React TypeScript Cheatsheet中明确:空接口{}和Object类型代表任意非空值,而非字面意义上的“空对象”。以下TypeScript代码可验证该结论:
let value: {}; value = 1; value = "foo"; value = () => alert("foo"); value = {}; value = { foo: "bar" }; value = undefined; // 类型错误 value = null; // 类型错误
从示例可见,{}类型可匹配数字、字符串、函数、任意非空对象等,但无法赋值undefined或null。
基于这个认知,当组件定义为FC<{}>时,似乎Props应能接受任意非空值作为属性,但实际传递{ id: '1111' }时却触发类型错误:
const Child:FC<{}> = (props) => { return ( <div> Child </div> ) } const App = () => { return ( {/**Error: Type '{ id: string; }' is not assignable to type 'IntrinsicAttributes'.**/} <Child id={'111'}/> ); }
但普通变量赋值却完全正常:
let props: {} props = {id: '111'}
本质原因解析
核心原因在于React组件的JSX语法会被转译为createElement函数调用,而createElement的类型声明对Props做了特殊处理:
interface Attributes { key?: Key | null | undefined; } function createElement<P extends {}>( type: FunctionComponent<P>, props?: Attributes & P | null, ...children: ReactNode[] ): FunctionComponentElement<P>;
当定义组件:
const MyComponent = (props: {}) => <div>I am a child component</div>;
组件本身的Props类型确实是{}(任意非空值),但传入createElement后,实际校验的Props类型变为Attributes & P——即内置的Attributes接口(仅包含可选的key属性)与原P类型的交叉类型。
此时Props的有效属性被限制为仅key,因此会出现以下结果:
return ( <div className="App"> <MyComponent a="1" /> // 报错:额外属性'a'不被允许 <MyComponent key="1" /> // 正常:key属于Attributes接口的合法属性 </div> );
内容的提问来源于stack exchange,提问作者SuCan
相关产品推荐
相关产品推荐

