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

TypeORM Decimal类型列使用QueryBuilder查询返回字符串而非数字问题求解

问题原因

这是TypeORM底层数据库驱动的默认行为:JavaScript原生number类型存在精度上限(最大安全值为2^53 - 1),而数据库的decimal类型支持更高精度,为了避免精度丢失,驱动默认会把decimal类型的返回值序列化为字符串。

修复方案

下面提供三种适配不同场景的解决方案:

方案1:全局配置自动转换

如果你的项目中所有decimal字段的精度都不会超过16位,不会触发JS的精度丢失问题,可以直接在TypeORM连接配置中添加参数,全局开启decimal自动转数值的能力,以MySQL为例:

// typeorm配置文件
export default {
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: '你的数据库密码',
  database: '你的数据库名',
  entities: [CollectionStats],
  synchronize: false,
  // 新增以下配置
  extra: {
    decimalNumbers: true
  }
}

配置生效后,所有查询返回的decimal字段都会自动转为number类型,普通find查询和QueryBuilder查询都生效。

方案2:针对指定字段添加转换器

如果不需要全局修改,只想处理部分decimal字段,可以在实体的Column装饰器中添加自定义转换器:

// 先定义通用转换器
const decimalTransformer = {
  // 数据入库时的转换逻辑,直接传入数值即可
  to: (value: number) => value,
  // 查询返回时的转换逻辑,将字符串转为数值
  from: (value: string) => parseFloat(value)
}

// 实体字段修改为如下写法
@Column("decimal", { transformer: decimalTransformer })
one_day_volume: number;

// 其余需要转换的decimal字段都按上述格式修改即可

如果你的decimal字段精度很高,担心转number丢失精度,也可以将from方法的返回值改为高精度实例,比如引入big.js后返回Big(value)即可。

方案3:单次查询手动转换

如果只是临时处理某一次QueryBuilder的查询结果,可以拿到返回值后手动做类型转换:

const result = await dataSource
  .getRepository(CollectionStats)
  .createQueryBuilder('stats')
  .where('stats.id = :id', { id: 1 })
  .getOne()

// 手动转换字段类型
result.one_day_volume = parseFloat(result.one_day_volume as unknown as string)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:15:03