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

如何对Expense对象due属性的Timestamp|string联合类型进行类型收窄?

如何正确收窄Timestamp | string类型以访问seconds属性?

问题背景

从API获取Expense[]类型数组,其中Expense的due属性为Timestamp对象或string类型。需要从Timestamp对象中提取seconds属性并格式化为字符串展示,希望避免使用类型断言,尝试过in关键字和satisfies但未成功,当前代码依赖类型断言才能运行。

简化后的类型定义与代码:

interface Timestamp {
  seconds: number;
  nanoseconds: number;
}

interface Expense {
  name: string;
  amount: number;
  remaining: number;
  due: Timestamp | string;
  notes: string;
  category: string;
}

this.expenses = expenses.map((expense) => {
        if (typeof expense.due !== 'string') {
          return { ...expense, due: this.formatDate(expense.due.seconds * 1000) } as Expense;
        }
      }) as Expense[];

formatDate(milliseconds: number) {
    return new Intl.DateTimeFormat('en-ca', {
      weekday: 'short',
      day: 'numeric',
      year: 'numeric',
    }).format(new Date(milliseconds));
  }

解决方案

你的核心思路没问题,typeof expense.due !== 'string'已经能正确将due收窄为Timestamp类型,问题出在**map函数缺少else分支的返回值**,导致TypeScript无法确定所有情况都返回Expense类型,才需要额外断言。修正方式如下:

修正后的代码

this.expenses = expenses.map((expense) => {
  // typeof判断已完成类型收窄,无需断言
  if (typeof expense.due !== 'string') {
    return { 
      ...expense, 
      due: this.formatDate(expense.due.seconds * 1000) 
    };
  }
  // 补全else分支,返回原expense(或根据需求处理string类型的due)
  return expense;
});

关键说明

  1. 补全返回分支:map函数要求每个迭代都返回对应类型的值,原代码中当due是string时没有返回值,导致数组可能混入undefined,TypeScript只能通过断言强制类型。补全return expense后,TypeScript能自动推导出返回值为Expense类型,无需as Expense断言。
  2. typeof的有效性:typeof expense.due !== 'string'可以准确排除string类型,剩下的自然是Timestamp类型,TypeScript会自动认可expense.due.seconds的访问。
  3. 替代收窄方式(可选):如果需要更明确的类型判断,也可以用in关键字检查属性:
    if ('seconds' in expense.due) {
      // 此时due已收窄为Timestamp类型
      return { ...expense, due: this.formatDate(expense.due.seconds * 1000) };
    }
    return expense;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:25:02