React 18迁移:自定义类型覆盖后children属性类型报错求助
迁移到React 18后,React.FunctionComponent(简称React.FC)不再默认包含children属性,需要在组件Props中显式声明。为避免手动修改数百个组件,我们尝试通过自定义index.d.ts类型文件覆盖React类型,保留旧版React.FC自带children的行为,但编写Demo组件时出现以下类型错误:
Property 'children' does not exist on type 'IProps | PropsWithChildren<IProps>'
错误原因
原自定义类型通过扩展React模块的FunctionComponent接口添加了新的调用签名,TypeScript会合并原接口的调用签名((props: P, context?: any) => ReactElement<any, any> | null)与自定义的调用签名((props: PropsWithChildren<P>, context?: any) => ReactElement<any, any> | null),最终组件的props类型被推断为IProps | PropsWithChildren<IProps>。由于IProps未声明children,联合类型下无法直接访问该属性,因此报错。
解决方案
放弃接口扩展的方式,直接用类型别名重新定义React.FC和React.FunctionComponent,让它们的props参数直接指向PropsWithChildren<P>,替换原有的类型定义:
// index.d.ts import * as React from 'react'; declare module 'react' { type FC<P = {}> = (props: React.PropsWithChildren<P>, context?: any) => React.ReactElement<any, any> | null; type FunctionComponent<P = {}> = FC<P>; }
验证
修改类型定义后,原有Demo组件无需任何改动即可正常运行:
interface IProps { age: number } const Demo: React.FunctionComponent<IProps> = ({ children, age }) => ( <> {children} {age} </> ); <Demo age={10}>Hi</Demo>
这样既保留了React.FC的原有使用方式,又让组件能正确解构children属性,无需逐个修改组件的Props声明。
内容的提问来源于stack exchange,提问作者ajm

