TypeOrm-Postgres-NestJs中@Column('decimal')返回字符串的全局解决需求
全局解决TypeOrm + Postgres中Decimal字段返回字符串的问题
方法一:自定义全局Decimal类型(推荐,覆盖所有场景)
这个方法会替换TypeOrm对Postgres decimal 类型的默认处理逻辑,不管是实体字段还是聚合查询的结果,都会自动转换为数值类型。
- 创建自定义Decimal类型文件(比如
src/common/types/decimal-number.type.ts)
import { Type } from 'typeorm'; export class DecimalNumberType extends Type { getColumnType(): string { return 'decimal'; } toDatabaseValue(value: number): string { // 写入数据库时转字符串,避免精度丢失 return value?.toString(); } fromDatabaseValue(value: string): number { // 从数据库读取时转数值 return value ? parseFloat(value) : null; } }
- 在NestJs的TypeOrm配置中全局注册该类型
在app.module.ts的TypeOrmModule配置里添加extra.types:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { DecimalNumberType } from './common/types/decimal-number.type'; import { YourEntity } from './entities'; // 替换为你的实体 @Module({ imports: [ TypeOrmModule.forRoot({ type: 'postgres', host: 'localhost', port: 5432, username: 'your-username', password: 'your-password', database: 'your-db', entities: [YourEntity], synchronize: false, // 生产环境建议关闭 extra: { types: [ { name: 'decimal', type: DecimalNumberType, }, ], }, }), ], }) export class AppModule {}
方法二:全局实体订阅者(仅处理实体字段,聚合查询需额外处理)
如果不想自定义类型,可以通过实体订阅者自动给所有decimal字段添加转换器,但注意聚合查询的原始结果可能不会触发这个转换,需要配合getRawMany()后的手动处理,或者结合方法一使用。
- 创建订阅者文件(比如
src/common/subscribers/decimal-transformer.subscriber.ts)
import { EntitySubscriberInterface, EventSubscriber, LoadEvent } from 'typeorm'; @EventSubscriber() export class DecimalTransformerSubscriber implements EntitySubscriberInterface { beforeLoad(event: LoadEvent<any>) { const columns = event.metadata.columns; columns.forEach(column => { if (column.type === 'decimal' && !column.transformer) { column.transformer = { to: (val: number) => val?.toString(), from: (val: string) => val ? parseFloat(val) : null, }; } }); } }
- 在TypeOrm配置中注册订阅者
TypeOrmModule.forRoot({ // 其他配置... subscribers: [DecimalTransformerSubscriber], })
注意事项
- 聚合查询(如
SUM,AVG)返回的原始结果,方法一的自定义类型会自动处理,因为TypeOrm会根据数据库返回的类型调用对应的转换逻辑; - 如果使用
getRawMany(),方法一同样生效,无需额外处理; - 若担心
parseFloat精度问题,可以用Number(value)或者第三方库(如decimal.js)处理,但Postgres的decimal精度如果在JavaScript数值范围内,parseFloat足够。
内容的提问来源于stack exchange,提问作者anmolpansari
相关产品推荐
相关产品推荐

