React 18 TypeScript中如何定义非可选的defaultProps
React函数组件中为必填Props设置默认值的正确姿势
在React + TypeScript的函数组件中,官方推荐通过函数参数默认值设置props默认值,但这种方式仅适用于标记为可选(?)的属性。如果想给必填Props设置默认值,同时避免将其设为可选(防止外部传入undefined或漏传值导致崩溃),可以用以下几种方案解决:
方案1:拆分内外Props类型
通过定义外部暴露的必填Props类型,以及内部组件接收的可选Props类型(结合默认参数),同时用类型断言让组件对外暴露正确的必填约束:
import React from 'react'; // 外部调用时必须遵守的Props:importantProp为必填,禁止传入undefined interface RequiredProps { importantProp: string; } // 内部组件接收的Props:允许importantProp可选(因为有默认值兜底) type InternalProps = Omit<RequiredProps, 'importantProp'> & Partial<Pick<RequiredProps, 'importantProp'>>; // 组件对外暴露RequiredProps类型,内部使用InternalProps处理默认值 const ImportantComponent: React.FC<RequiredProps> = ({ importantProp = '默认值' }: InternalProps) => { return <div>{importantProp}</div>; }; // 使用示例 const App = () => { return ( <> <ImportantComponent /> {/* 正常,自动使用默认值 */} <ImportantComponent importantProp="自定义内容" /> {/* 正常 */} <ImportantComponent importantProp={undefined} /> {/* TS报错:undefined无法赋值给string */} </> ); };
方案2:使用函数重载
通过TypeScript的函数重载,明确组件的两种合法调用方式:不传目标Props(用默认值)、传合法的string值,直接禁止传入undefined的情况:
import React from 'react'; interface Props { importantProp: string; } // 重载1:不传importantProp,使用默认值 function ImportantComponent(): React.ReactElement; // 重载2:传入合法的importantProp function ImportantComponent(props: Props): React.ReactElement; // 组件实现:接收可选的props,设置默认值 function ImportantComponent(props?: Partial<Props>) { const { importantProp = '默认值' } = props || {}; return <div>{importantProp}</div>; } // 使用示例 const App = () => { return ( <> <ImportantComponent /> {/* 正常 */} <ImportantComponent importantProp="自定义内容" /> {/* 正常 */} <ImportantComponent importantProp={undefined} /> {/* TS报错:无匹配的重载签名 */} </> ); };
方案3:自定义工具类型复用逻辑
如果多个组件或多个Props需要类似处理,可以自定义Defaultize工具类型,将指定的必填Props转为可选,同时保留其他必填项的约束:
import React from 'react'; // 自定义工具类型:将指定的必填属性转为可选,用于设置默认值 type Defaultize<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; interface Props { importantProp: string; otherRequiredProp: number; // 其他必须传入的属性 } // 组件接收处理后的Props,设置importantProp的默认值 const ImportantComponent = ({ importantProp = '默认值', otherRequiredProp }: Defaultize<Props, 'importantProp'>) => { return ( <div> {importantProp} - {otherRequiredProp} </div> ); }; // 使用示例 const App = () => { return ( <> {/* 必须传otherRequiredProp,importantProp可选 */} <ImportantComponent otherRequiredProp={123} /> {/* 正常,使用默认值 */} <ImportantComponent otherRequiredProp={456} importantProp="自定义内容" /> {/* 正常 */} <ImportantComponent otherRequiredProp={789} importantProp={undefined} /> {/* TS报错 */} <ImportantComponent /> {/* TS报错:缺少otherRequiredProp */} </> ); };
注意事项
- 避免使用
Component.defaultProps:官方已不推荐在函数组件中使用该方式,且结合TypeScript容易出现类型不一致问题。 - 以上方案均保证:组件内部的
importantProp始终为合法的string类型,外部调用时要么不传(用默认值),要么传合法的string,禁止传入undefined。
内容的提问来源于stack exchange,提问作者Kipnoedels
相关产品推荐
相关产品推荐

