typeorm: docs do not describe how bigint type is treated as string to avoid rounding issues

Issue type:

[ ] question [ ] bug report [ ] feature request [x] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [ ] mysql / mariadb [ ] oracle [x] postgres [ ] sqlite [ ] sqljs [ ] react-native

TypeORM version:

[ ] latest [ ] @next [x] 0.2.7 (or put your version here)

Steps to reproduce or a small repository showing the problem:

I ran console.log(entity, typeof entity.myBigIntColumn) and noticed that my column was a string instead of Number. This makes sense because the maximum postgres bigint value is 9223372036854775807 and yet in JavaScript Number.MAX_SAFE_INTEGER is 9007199254740991. However, the documentation at http://typeorm.io/#/entities/column-types-for-postgres doesn’t mention that at all.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 36
  • Comments: 28 (6 by maintainers)

Commits related to this issue

Most upvoted comments

I just wanted to point out that this issue means that the type definitions for methods like find and findOne are incorrect. If you have an entity that looks like this:

@Entity()
export class Person {
    @PrimaryColumn() public name!: string;

    @Column({ type: 'bigint' })
    public age!: number;
}

And you call findOne like this:

const person = await personRepository.findOne({where: {name: 'Alice'}});

The TypeScript compiler thinks that person has type Person because that is what the type definition for findOne specifies. But in reality the type of the person.age will be string instead of number. This can lead to some surprising and confusing errors.

I’ll leave some bread crumbs because I got this to work for my application.

In creating the the TypeOrm connection, I’m using Nest but that doesn’t matter, you can add the option

      bigNumberStrings: false,

And typescript 3.2 supports bigint types.

We can therefor declare:

  @PrimaryGeneratedColumn({type: 'bigint'})
  public id: bigint;

This works for me and presents no risk of overflow. I hope this helps.

I had same struggle in recent…

So, from the following comment, I guess TypeORM is not planning to support bigint using third-party library, right? If so, it would be wonderful to have document updated, maybe in column types section.


For solution, I guess it would be either use ValueTransformer to set as number which is optimistic but easy way and the another is to use string which is most safest but more work needed option.

Here’s my solution snippet using ValueTranformer. One notice is that I had to specify Generated decorator in order to transform after it retrieve the data. Not sure why this decorator is needed but if you use bigint in non-generated column, it might be better to use string.

export const bigint: ValueTransformer = {
  to: (entityValue: number) => entityValue,
  from: (databaseValue: string): number => parseInt(databaseValue, 10)
}

@Entity()
export class User {
  @Generated('increment')
  @PrimaryColumn('bigint', { transformer: [bigint] })
  id: number

  @Column('varchar', { length: 255 })
  name: string
}

BTW, I tried to convert into BigInt using ValueTransformer like following, but it ends up with failure because JSON.stringify doesn’t support BigInt, used in find methods. It seems there’s no plan to support BigInt in JSON serialization for a moment as it’s been discussed in tc39 proposal issue.

export const bigint: ValueTransformer = {
  to: (entityValue: bigint) => entityValue,
  from: (databaseValue: string): bigint => BigInt(databaseValue)
}

@Entity()
export class User {
  @PrimaryColumn('bigint', { transformer: [bigint] })
  id: bigint

  @Column('varchar', { length: 255 })
  name: string
}

Yeah… I lost an hour or so figuring this out

The solution that i used:

@Column('bigint', {
    transformer: {
      to: (value) => value,
      from: (value) => parseInt(value),
    },
  })
  orderId: number;

Database: Postgres

@takayukioda’s solution is great. However, it caused an issue because my column is nullable, resulting in NaN.

So I went for

const bigintTransformer: ValueTransformer = {
  to: (entityValue: bigint) => entityValue,
  from: (databaseValue: string | null): number | null => (databaseValue === null ? null : parseInt(databaseValue, 10)),
};

I’ll leave some bread crumbs because I got this to work for my application.

In creating the the TypeOrm connection, I’m using Nest but that doesn’t matter, you can add the option

      bigNumberStrings: false,

And typescript 3.2 supports bigint types.

We can therefor declare:

  @PrimaryGeneratedColumn({type: 'bigint'})
  public id: bigint;

This works for me and presents no risk of overflow. I hope this helps.

This does not make the id become a bigint. If you check the type of id at runtime, it would be number or string depending on the value.

If bigint will always be returned at runtime as a string (unless you use a transformer), is there a way to have the decorator enforce that the typescript type must be a string?

I think it would be better if it were in the Entities area of the docs. That is where people would look for this information. Also, the types of the various data types is something I expect to be discussed there—I was surprised not to find anything in the docs for that.

It worked for me when i did the following:

var types = require('pg').types;
types.setTypeParser(20, BigInt);

Then it retrieves it as a bigint instead of a int.

I’ll leave some bread crumbs because I got this to work for my application.

In creating the the TypeOrm connection, I’m using Nest but that doesn’t matter, you can add the option

      bigNumberStrings: false,

And typescript 3.2 supports bigint types.

We can therefor declare:

  @PrimaryGeneratedColumn({type: 'bigint'})
  public id: bigint;

This works for me and presents no risk of overflow. I hope this helps.

Thank you very much. That worked like a charm.

Typeorm still doesn’t handle biginteven with es2020+ As @u128393 wrote, for bigNumberStrings: false and bigint type, the value is returned as a number.

Do we just want the docs updated to basically reflect that number types with floating points or big ints are returned as strings? I ran into this problem as well with MySQL decimal type.

@DanielLoyAugmedix I tried what you mentioned, and I still end up getting a string literal in place of a bigint for the specific column. I added bigNumberStrings: false when creating TypeOrm connection. The above mentioned option only applies to MySQL. To solve the issue for postgres, I did the following,

var types = require('pg').types;

types.setTypeParser(20, function(val) {
  return parseInt(val);
});

Maybe we should add this one to FAQ. btw next edition of EcmaScript is going to add big ints so I think we’ll resolve issue with string bigint numbers in a near future.

Yes. This can’t happen soon enough.

What about polyfilling with any of the various big int libs as an interim step? Would that help or create more issues?