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

TypeScript中检测null的基础类型守卫失效问题排查

问题描述

我编写了名为isLegacyPayment的类型守卫,当判断出payment是遗留支付(stripeId为null)时抛出错误,但后续代码中TypeScript仍判定payment.stripeId可能为null。不想使用反向守卫isNotLegacyPayment,因为这个命名容易引发开发者混淆,希望修复isLegacyPayment使其正常工作。

报错信息

Type 'string | null' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'.(2322)

原始代码

type Payment = {
  stripeId: null | string;
}

function isLegacyPayment<T extends Pick<Payment, 'stripeId'>>(payment: T): payment is T & { stripeId: null } {
  return payment.stripeId === null;
}


function test() {
  const payment: Payment = { stripeId: '12321' };

  if (isLegacyPayment(payment)) {
    throw new Error('Is legacy payment');
  }

  const stripeId: string = payment.stripeId; // 此处出现类型错误
}
解决方案

问题根源在于类型守卫的泛型定义没有让TypeScript正确识别:当守卫返回true并抛出错误后,剩余代码中的payment类型应该被缩小为stripeId必为string的版本。

方案一:简化类型守卫定义

直接去掉泛型,明确守卫的判断类型:

function isLegacyPayment(payment: Payment): payment is { stripeId: null } {
  return payment.stripeId === null;
}

方案二:保留泛型并调整约束

如果需要支持Payment的子类型,修改泛型约束为直接继承Payment:

function isLegacyPayment<T extends Payment>(payment: T): payment is T & { stripeId: null } {
  return payment.stripeId === null;
}

修改后,TypeScript会正确推断:当isLegacyPayment(payment)为true并抛出错误时,后续代码中的payment.stripeId必然是string类型,不会再出现类型错误。

内容的提问来源于stack exchange,提问作者Noitidart

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 10:53:22