Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Precision Option for int64 Handling in ts-proto #1161

Open
CrazyCodingBanana opened this issue Feb 14, 2025 · 0 comments
Open

Add Precision Option for int64 Handling in ts-proto #1161

CrazyCodingBanana opened this issue Feb 14, 2025 · 0 comments

Comments

@CrazyCodingBanana
Copy link

CrazyCodingBanana commented Feb 14, 2025

Currently, ts-proto provides various options for handling int64 fields via the forceLong option.

In my use case, I have a custom timestamp message that is defined as an int64.
I receive queries as an encoded AST that ts-proto helps me decode, but we encountered an edge case where decoding int64 thats bigger than the SAFE_MAX_INTEGER throws a runtime exception, as noted in the ts-proto documentation.
To handle this issue, I currently annotate the message with a different type and manually convert it post-decoding to a number
This issue made me think of better alternative that could save time and reduce manual conversions.

Option : Add a Precision Option for int64 Handling.

Introduce a ts-proto option that allows specifying a precision level for int64 timestamps.
Since UNIX timestamps are often stored as int64, this option would allow automatic conversion to a lower precision unit when decoding.

--ts_proto_opt=int64_precision=milli

Possible values:

nano (default) → Keeps the full int64 value (current behavior).
micro → Converts int64 to microseconds by dividing by 1_000.
milli → Converts int64 to milliseconds by dividing by 1_000_000.

this should create a function that tries to trim the number before checking it

function longToNumber(long: Long, precision: "nano" | "micro" | "milli" = "nano"): number {
  let divisor = 1;

  switch (precision) {
    case "micro":
      divisor = 1_000; // Convert nanoseconds to microseconds
      break;
    case "milli":
      divisor = 1_000_000; // Convert nanoseconds to milliseconds
      break;
  }

  const scaledValue = long.div(divisor); 

  if (scaledValue.gt(globalThis.Number.MAX_SAFE_INTEGER)) {
    throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER after precision scaling");
  }
  if (scaledValue.lt(globalThis.Number.MIN_SAFE_INTEGER)) {
    throw new globalThis.Error("Value is smaller than Number.MIN_SAFE_INTEGER after precision scaling");
  }

  return scaledValue.toNumber();
}

I wanted to gather opinions whether this would be accepted as a PR on my behalf and if this is a valid idea at all,
or maybe you have other ideas i can improve on my issue via contributing.
I would love to know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant