You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

TypeScript报错:类型'undefined'无法赋值给'number | bigint'排查

TypeScript报错:number | undefined 无法赋值给 number | bigint,但控制台显示值为数字

我在格式化API返回的数字数据时遇到了TypeScript类型错误,奇怪的是控制台明明能打印出预期的数字格式响应,但TypeScript就是不接受这个值。

相关代码

import React, { useEffect, useState } from 'react';
import api from '../../services';
import { CardsList, Value } from './styles';

interface ContractProps {
 data: {
  dataCards: {
   billing: {
    monthlyBilling: number;
   };
  }
 }
}

const Cards: React.FC = () => {
 const [contract, setContract] = useState<ContractProps>();
 const monthlyBillingData = contract?.data.dataCards.billing.monthlyBilling;

 useEffect(() => {
  api.get('').then(response => {
   setContract(response.data);
  });
 }, []);

 console.log(monthlyBillingData);
 console.log(typeof(monthlyBillingData));
 console.log(new Intl.NumberFormat().format(monthlyBillingData));

 return (
  <CardsList>
   <h3>Ativos</h3>
   <Value>
    <strong>R$ {contract?.data.dataCards.billing.monthlyBilling}</strong>
   </Value>
  </CardsList>
 );
};

export default Cards;

报错信息

No overload matches this call. Overload 1 of 2, '(value: number | bigint): string', gave the following error.
Argument of type 'number | undefined' is not assignable to parameter of type 'number | bigint'.
Type 'undefined' is not assignable to type 'number | bigint'.
Overload 2 of 2, '(value: number): string', gave the following error.
Argument of type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'. TS2769

控制台输出

100000
number
100,000

问题原因分析

其实这个问题的核心是TypeScript的静态类型检查逻辑和代码运行时的执行顺序不匹配

  • 组件初始化时,contract的初始值是undefined(因为你给useState指定了ContractProps泛型,但没有传入初始值,所以默认状态是undefined),因此monthlyBillingData的类型被TypeScript推断为number | undefined
  • 虽然你在useEffect里通过异步请求更新了contract的值,但TypeScript是编译期静态类型检查工具,它没办法预知异步操作的执行时机和结果——它只根据代码的静态结构判断类型,不会考虑运行时的数据流变化。
  • Intl.NumberFormat().format()方法的参数明确要求是number | bigint类型,不接受undefined,所以TypeScript就抛出了类型不兼容的错误。

解决方案

这里提供几种常见的解决思路:

1. 空值合并运算符设置默认值

monthlyBillingData一个兜底的数字值(比如0),确保参数永远是数字类型:

console.log(new Intl.NumberFormat().format(monthlyBillingData ?? 0));

2. 类型守卫判断值存在后再执行

通过条件判断排除undefined的情况,让TypeScript知道此时值是确定的数字:

if (monthlyBillingData !== undefined) {
  console.log(new Intl.NumberFormat().format(monthlyBillingData));
}

3. 给useState设置符合结构的初始值

直接给contract一个符合ContractProps结构的初始值,从根源上避免undefined

const [contract, setContract] = useState<ContractProps>({
  data: {
    dataCards: {
      billing: {
        monthlyBilling: 0
      }
    }
  }
});

4. 渲染时处理undefined情况

在JSX渲染时也做类型判断,确保展示的内容是合法的:

<Value>
  <strong>R$ {monthlyBillingData ? new Intl.NumberFormat().format(monthlyBillingData) : '0'}</strong>
</Value>

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

火山引擎 最新活动