Saltar al contenido principal
06Tipos de datos primitivos

BigInt

Clase 4 de 510 min de lectura

En la clase anterior vimos que number se queda sin precisión con los enteros muy grandes. BigInt es el primitivo que lo arregla: llegó en ES2020 (ES11) para representar enteros de tamaño arbitrario, tan grandes como aguante la memoria.

¿Por qué necesitamos BigInt?#

Porque con number, pasado cierto límite, las cuentas dejan de salir. Sigue este ejemplo línea a línea:

// Límite del tipo numberconst bigNumber = 30000000000000000console.log(bigNumber) // -> 30000000000000000// Si le sumáramos 1 a este número, el resultado debería ser:// 30000000000000001// Pero si lo intentas sumar con JS, el resultado es diferente:console.log(bigNumber + 1) // -> 30000000000000000console.log(bigNumber + 2) // -> 30000000000000000 (¡igual!)// Incluso con números grandes, puedes perder precisiónlet numeroGrande = 1234567890123456789console.log(numeroGrande) // -> 1234567890123456800 (¡redondeado!)

Sumas y el número no se mueve. Con BigInt el problema desaparece. Fíjate en la n del final:

// Con BigInt mantenemos la precisiónlet numeroGrandeBigInt = 1234567890123456789nconsole.log(numeroGrandeBigInt) // -> 1234567890123456789n (¡exacto!)console.log(numeroGrandeBigInt + 1n) // -> 1234567890123456790n (¡exacto!)
Infografía
El límite de los enteros seguros
4.Con BigInt (el sufijo n) existen todos los enteros, sin límite: 9007199254740991n + 2n da el resultado exacto.
Paso 4 de 4

Creación de BigInt#

Tienes dos formas de crear un BigInt: añadir el sufijo n al número o usar la función BigInt(). En ambos casos obtienes un primitivo, así que typeof devuelve 'bigint'.

1. Literal BigInt (sufijo 'n')

Escribes el entero y le pegas una n detrás:

// Enteros con sufijo 'n'let grande1 = 123nlet grande2 = 9007199254740991nlet grande3 = 1234567890123456789012345678901234567890nconsole.log(typeof grande1) // -> 'bigint'

2. Constructor BigInt()

Cuando el valor te llega en una variable, pásaselo a BigInt(). Acepta un número entero o una cadena de texto, también en hexadecimal o binario:

// Desde número (si está en rango seguro)let desdeEntero = BigInt(123) // -> 123nlet desdeEnteroGrande = BigInt(9007199254740991) // -> 9007199254740991n// Desde stringlet desdeString = BigInt('123456789012345678901234567890')// -> 123456789012345678901234567890n// Desde string hexadecimallet desdeHex = BigInt('0x1fffffffffffff') // -> 9007199254740991n// Desde string binarialet desdeBin = BigInt('0b11111111111111111111111111111111') // -> 4294967295n// Desde una variablelet numeroGrandeEnString = '123456789012345678901234567890'let desdeVariable = BigInt(numeroGrandeEnString) // -> 123456789012345678901234567890n

¿Por qué pasar un string si ya existen los números? Porque un number enorme ya habría perdido precisión antes de llegar a BigInt(). El texto, en cambio, conserva todos los dígitos.

3. Limitaciones en la creación

No todo se puede convertir en BigInt. Estos son los tres tropiezos típicos:

// ❌ No funciona con decimales// BigInt(3.14) // RangeError: The number 3.14 cannot be converted to a BigInt// ⚠️ Cuidado con números que ya están fuera del rango seguro de Number// BigInt(Number.MAX_SAFE_INTEGER + 2) // Puede dar resultados inesperados// ❌ No funciona con strings inválidos// BigInt("abc") // SyntaxError: Cannot convert abc to a BigInt

Operaciones con BigInt#

Igual que los números, los BigInt admiten operadores aritméticos, de comparación y bitwise.

Operaciones aritméticas básicas

Todo funciona como esperas, con una excepción: la división descarta los decimales.

let a = 100nlet b = 200n// Operaciones básicasconsole.log(a + b) // -> 300nconsole.log(a - b) // -> -100nconsole.log(a * b) // -> 20000nconsole.log(b / a) // -> 2n (división entera)console.log(b % a) // -> 0n (módulo)console.log(a ** 2n) // -> 10000n (exponenciación)// ¡Ojo! La división siempre es entera, no te da los decimalesconsole.log(7n / 2n) // -> 3n (no 3.5)console.log(10n / 3n) // -> 3n (no 3.333...)

Comparaciones

Entre BigInt no hay misterio. Lo interesante viene al compararlos con un number normal:

let x = 100nlet y = 200n// Comparaciones funcionan normalmenteconsole.log(x < y) // -> trueconsole.log(x > y) // -> falseconsole.log(x === 100n) // -> trueconsole.log(x !== y) // -> true// Comparación con números regularesconsole.log(100n == 100) // -> true (coerción)console.log(100n === 100) // -> false (tipos diferentes)console.log(100n < 101) // -> trueconsole.log(100n > 99) // -> true

100n y 100 valen lo mismo, pero son de tipos distintos, por eso la igualdad estricta dice false. En cambio, < y > sí comparan por valor.

Operaciones bitwise

Las operaciones bitwise trabajan bit a bit. Son más avanzadas que las aritméticas, y con BigInt también funcionan:

let bits1 = 0b1010n // -> 10nlet bits2 = 0b1100n // -> 12n// Operadores bitwiseconsole.log(bits1 & bits2) // -> 8n (AND)console.log(bits1 | bits2) // -> 14n (OR)console.log(bits1 ^ bits2) // -> 6n (XOR)console.log(~bits1) // -> -11n (NOT)console.log(bits1 << 2n) // -> 40n (shift left)console.log(bits1 >> 1n) // -> 5n (shift right)

Restricciones importantes#

BigInt es otro tipo, y no siempre encaja donde encajaba un number. Hay tres sitios donde vas a chocar, y el primero es el que más problemas da.

No se puede mezclar con Number

Si juntas un BigInt y un number en una operación aritmética, JavaScript lanza un error:

Consola
Escribes:100n + 50
Error:Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

El propio error te da la solución: decide tú a qué tipo conviertes.

let bigint = 100nlet number = 50// ❌ Esto no funciona// console.log(bigint + number) // TypeError: Cannot mix BigInt and other types// ✅ Hay que convertir explícitamenteconsole.log(bigint + BigInt(number)) // -> 150nconsole.log(Number(bigint) + number) // -> 150// ✅ O usar comparaciones que permiten coerciónconsole.log(bigint > number) // -> true

No funciona con Math

Los métodos de Math están pensados para number y rechazan los BigInt:

let grande = 100n// ❌ Math no acepta BigInt// Math.sqrt(grande) // TypeError: Cannot convert a BigInt value to a number// Math.max(10n, 20n) // TypeError// ✅ Usa operaciones nativas de BigIntconsole.log(grande ** 2n) // -> 10000n para potencias

No se puede usar con JSON

JSON.stringify() no sabe qué hacer con un BigInt. La salida es convertirlo antes a string:

let objeto = {  numero: 42,  grande: 123n}// ❌ JSON.stringify no maneja BigInt// JSON.stringify(objeto) // TypeError: Do not know how to serialize a BigInt// ✅ Solución: convertir a stringlet objetoSerializable = {  numero: objeto.numero,  grande: objeto.grande.toString()}console.log(JSON.stringify(objetoSerializable))// -> {"numero":42,"grande":"123"}

Métodos de BigInt#

Métodos estáticos

Dos métodos para encajar un valor en un número concreto de bits. Lo que no cabe, se recorta:

// BigInt.asIntN() - convierte a entero con signo de N bitsconsole.log(BigInt.asIntN(8, 300n)) // -> 44n (300 en 8 bits con signo)// BigInt.asUintN() - convierte a entero sin signo de N bitsconsole.log(BigInt.asUintN(8, 300n)) // -> 44n (300 en 8 bits sin signo)console.log(BigInt.asUintN(8, -1n)) // -> 255n (-1 en 8 bits sin signo)

Conversiones#

De BigInt a otros tipos

let grande = 123456789n// A Number (cuidado con la precisión)let comoNumber = Number(grande) // -> 123456789console.log(typeof comoNumber) // -> 'number'// A Stringlet comoString = String(grande) // -> '123456789'let comoStringDirect = grande.toString() // -> '123456789'// A Booleanlet comoBoolean = Boolean(grande) // -> trueconsole.log(Boolean(0n)) // -> false

De otros tipos a BigInt

// Desde Number (solo enteros en rango seguro)let desdeNumber = BigInt(42) // -> 42n// Desde Stringlet desdeString = BigInt('123456789012345678901234567890')// Desde Booleanlet desdeTrue = BigInt(true) // -> 1nlet desdeFalse = BigInt(false) // -> 0n

En resumen

  • BigInt representa enteros de cualquier tamaño sin perder precisión, más allá de Number.MAX_SAFE_INTEGER.
  • Se crea con el sufijo n (123n) o con BigInt().
  • Solo enteros: no admite decimales y la división descarta el resto.
  • No se mezcla con Number en operaciones aritméticas: convierte explícitamente.
  • No funciona con Math ni se serializa en JSON.

Palabras finales sobre BigInt#

No vas a necesitar BigInt todos los días. Suele aparecer en criptografía o en temas financieros, donde no te puedes permitir perder información al operar con números muy grandes. Y recuerda que los navegadores antiguos no lo soportan.