or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdprecision-numbers.mdrecord-marshalling.mdvalue-conversion.md
tile.json

precision-numbers.mddocs/

Precision Numbers

Specialized handling for numbers that exceed JavaScript's Number.MAX_SAFE_INTEGER and MIN_SAFE_INTEGER limits. The NumberValue class maintains full precision by storing numbers as strings while providing conversion utilities for different numeric representations.

Capabilities

NumberValue Class

A class for storing DynamoDB numbers that exceed the scale of JavaScript's safe integer limits or require decimal precision beyond JavaScript's capabilities.

/**
 * Class for storing DynamoDB numbers that exceed the scale of
 * JavaScript's MAX_SAFE_INTEGER and MIN_SAFE_INTEGER, or the
 * decimal precision limit.
 * 
 * This class does not support mathematical operations in JavaScript.
 * Convert the contained string value to your application-specific
 * large number implementation to perform mathematical operations.
 */
class NumberValue {
  /** The precise number stored as a string */
  readonly value: string;

  /**
   * Creates a new NumberValue instance
   * @param value - A precise number as string, BigInt, number, or AttributeValue
   */
  constructor(value: number | Number | BigInt | string | { N: string });

  /**
   * Static factory method for creating NumberValue instances
   * @param value - A precise number as string, BigInt, number, or AttributeValue
   */
  static from(value: number | Number | BigInt | string | { N: string }): NumberValue;

  /**
   * Converts to DynamoDB AttributeValue format
   * @returns The AttributeValue form for DynamoDB
   */
  toAttributeValue(): { N: string };

  /**
   * Converts to BigInt representation
   * @returns BigInt representation
   * @throws SyntaxError if the string representation is not convertable to a BigInt
   */
  toBigInt(): bigint;

  /**
   * Returns string representation (canonical format in DynamoDB)
   * @returns String representation
   */
  toString(): string;

  /**
   * Returns the string value (same as toString)
   * @returns String representation
   */
  valueOf(): string;
}

Creating NumberValue Instances

NumberValue can be created from various numeric types while preserving precision:

import { NumberValueImpl as NumberValue } from "@aws-sdk/util-dynamodb";

// From string (recommended for precision)
const precise = new NumberValue("12345678901234567890.123456789");
console.log(precise.value); // "12345678901234567890.123456789"

// From BigInt
const fromBigInt = new NumberValue(12345678901234567890n);
console.log(fromBigInt.value); // "12345678901234567890"

// From regular number (safe integers only)
const fromNumber = new NumberValue(42);
console.log(fromNumber.value); // "42"

// From DynamoDB AttributeValue
const fromAttr = new NumberValue({ N: "999.999" });
console.log(fromAttr.value); // "999.999"

// Using static factory method
const factoryCreated = NumberValue.from("123.456");
console.log(factoryCreated.value); // "123.456"

Converting NumberValue

NumberValue provides methods to convert to different numeric representations:

import { NumberValueImpl as NumberValue } from "@aws-sdk/util-dynamodb";

const num = new NumberValue("12345678901234567890");

// Convert to DynamoDB format
const attrValue = num.toAttributeValue();
console.log(attrValue); // { N: "12345678901234567890" }

// Convert to BigInt (for integers)
const bigInt = num.toBigInt();
console.log(bigInt); // 12345678901234567890n

// Get string representation
const str = num.toString();
console.log(str); // "12345678901234567890"

// valueOf() returns string (not number)
const val = num.valueOf();
console.log(val); // "12345678901234567890"

Using with Marshall/Unmarshall

NumberValue integrates seamlessly with the marshalling functions:

import { marshall, unmarshall, NumberValueImpl as NumberValue } from "@aws-sdk/util-dynamodb";

// Marshall NumberValue instances
const data = {
  id: "item-1",
  preciseNumber: new NumberValue("12345678901234567890.123456789"),
  regularNumber: 42,
};

const marshalled = marshall(data);
console.log(marshalled);
// {
//   id: { S: "item-1" },
//   preciseNumber: { N: "12345678901234567890.123456789" },
//   regularNumber: { N: "42" }
// }

// Unmarshall with number wrapping
const dynamoRecord = {
  id: { S: "item-1" },
  largeNumber: { N: "12345678901234567890" },
  decimal: { N: "123.456" },
  regularNumber: { N: "42" },
};

const unwrapped = unmarshall(dynamoRecord, { wrapNumbers: true });
console.log(unwrapped);
// {
//   id: "item-1",
//   largeNumber: NumberValue { value: "12345678901234567890" },
//   decimal: NumberValue { value: "123.456" },
//   regularNumber: NumberValue { value: "42" }
// }

Error Handling and Validation

NumberValue constructor validates input to prevent precision loss:

import { NumberValueImpl as NumberValue } from "@aws-sdk/util-dynamodb";

// Safe numbers work fine
const safe = new NumberValue(42);                    // OK
const safeBig = new NumberValue(Number.MAX_SAFE_INTEGER); // OK

// Imprecise numbers throw errors
try {
  new NumberValue(Number.MAX_SAFE_INTEGER + 1);      // Throws error
} catch (error) {
  console.error(error.message); // "NumberValue should not be initialized with an imprecise number"
}

try {
  new NumberValue(NaN);                              // Throws error
} catch (error) {
  console.error(error.message); // "NumberValue should not be initialized with an imprecise number"
}

try {
  new NumberValue(Infinity);                         // Throws error
} catch (error) {
  console.error(error.message); // "NumberValue should not be initialized with an imprecise number"
}

// Use strings for precision
const precise = new NumberValue("12345678901234567890.123456789"); // OK

BigInt Conversion Errors

The toBigInt() method can throw errors for non-integer values:

import { NumberValueImpl as NumberValue } from "@aws-sdk/util-dynamodb";

const integer = new NumberValue("12345678901234567890");
const decimal = new NumberValue("123.456");

// Integer conversion works
const bigInt = integer.toBigInt(); // 12345678901234567890n

// Decimal conversion throws
try {
  decimal.toBigInt(); // Throws SyntaxError
} catch (error) {
  console.error(error.message); // "Cannot convert 123.456 to a BigInt"
}

Custom Number Handling

Use NumberValue with custom conversion functions for application-specific number handling:

import { unmarshall, NumberValueImpl as NumberValue } from "@aws-sdk/util-dynamodb";

const record = {
  price: { N: "19.99" },
  quantity: { N: "1000000000000000000" },
};

// Custom conversion function
const result = unmarshall(record, {
  wrapNumbers: (numString) => {
    // Use decimal.js or similar for precise decimals
    if (numString.includes('.')) {
      return parseFloat(numString); // or use Decimal library
    }
    // Use BigInt for large integers
    return BigInt(numString);
  }
});

console.log(result);
// { price: 19.99, quantity: 1000000000000000000n }