TypeScript误判元素可能为undefined,求优于非空断言的方案
解决联合类型Props的类型收窄问题
问题代码
interface HandleMapDefaultProps { item: { id: number } & Record<string, unknown>; renderCustomComponent?: never; } interface HandleMapCustomProps { renderCustomComponent: () => HTMLElement; item?: never; } type HandleMapProps = HandleMapDefaultProps | HandleMapCustomProps; const handleMap = ({ item, renderCustomComponent } : HandleMapProps): HTMLElement => renderCustomComponent?.() ?? <div>{item.id}</div>
报错信息
'item' is possibly 'undefined'
问题原因
虽然类型定义中item和renderCustomComponent是互斥关系,但解构后两个变量变成独立存在,TypeScript无法再跟踪它们之间的关联,因此无法自动推断出renderCustomComponent为undefined时item必然存在。
更优解决方案
方案1:保留原始Props对象,通过in操作符收窄类型
不提前解构Props,直接通过属性存在性判断让TypeScript自动收窄类型:
const handleMap = (props: HandleMapProps): HTMLElement => { if ('renderCustomComponent' in props && props.renderCustomComponent) { return props.renderCustomComponent(); } return <div>{props.item.id}</div>; };
这种方式下,TypeScript能明确识别两个分支对应的具体类型,不会再出现item可能为undefined的错误。
方案2:自定义类型守卫函数
通过自定义类型守卫,明确告知TypeScript当前Props的具体类型:
function isCustomProps(props: HandleMapProps): props is HandleMapCustomProps { return typeof props.renderCustomComponent === 'function'; } const handleMap = (props: HandleMapProps): HTMLElement => { if (isCustomProps(props)) { return props.renderCustomComponent(); } return <div>{props.item.id}</div>; };
类型守卫函数返回布尔值的同时,会向TypeScript传递类型信息,后续分支的类型会被正确推断。
方案3:解构后使用类型断言(相对方案1、2略逊)
如果一定要解构,可以用明确的类型断言替代非空断言!:
const handleMap = ({ item, renderCustomComponent } : HandleMapProps): HTMLElement => { if (renderCustomComponent) { return renderCustomComponent(); } return <div>{(item as HandleMapDefaultProps['item']).id}</div>; };
不过这种方式需要手动指定类型,不如前两种方案安全和直观。
内容的提问来源于stack exchange,提问作者Mike K
相关产品推荐
相关产品推荐

