You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 03:36:08