Skip to content

Conversation

theahmadshaikh
Copy link

feat(generator): add force_int64_string option to prevent int64 precision loss

Fixes #1229

Problem

Large 64-bit integers lose precision when mapped to JavaScript's number type in gRPC-Web generated TypeScript definitions. This is a well-known issue affecting JavaScript/TypeScript applications that work with large integers.

Example:

message User {
  int64 user_id = 1;
}

Generated TypeScript (current behavior):

getUserId(): number;  // ❌ Precision loss for values > 2^53
setUserId(value: number): void;

Problem demonstration:

const userId = 9024037547368883040;  // Large int64 value
console.log(userId);  // Output: 9024037547368883200 (precision lost!)

Solution

This PR adds a new CLI option force_int64_string=True that forces all int64/uint64 fields to be generated as string type, preserving full precision.

Usage:

protoc --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext,force_int64_string=True:. your_proto.proto

Generated TypeScript (with fix):

getUserId(): string;  // ✅ Full precision preserved
setUserId(value: string): void;

Implementation Details

  • New CLI option: force_int64_string=True
  • Backward compatible: Existing [jstype = JS_STRING] field-level option still works
  • Comprehensive coverage: Affects all 64-bit integer types (int64, uint64, sint64, fixed64, sfixed64)
  • Type-safe: Maintains TypeScript type safety with string-based integers

Changes Made

  1. Enhanced JSElementType function to check both jstype option and CLI flag
  2. Updated function signatures throughout the call chain to pass the force_int64_string parameter
  3. Added GeneratorOptions support for parsing the new CLI option
  4. Added test proto file to verify functionality

Testing

Default behavior: Normal fields → number, [jstype = JS_STRING]string
force_int64_string=True: All int64 fields → string
Backward compatibility: Existing behavior preserved

Migration Guide

For new projects:

# Use the new option to prevent precision loss
protoc --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext,force_int64_string=True:. your_proto.proto

For existing projects:

  • Continue using [jstype = JS_STRING] for specific fields
  • Or migrate to force_int64_string=True for global control

…sion loss

- Add CLI flag force_int64_string=True to force all int64/uint64 fields to string
- Enhance JSElementType function to check both jstype option and CLI flag
- Maintain backward compatibility with existing [jstype = JS_STRING] behavior
- Update function signatures to pass force_int64_string parameter through call chain
- Add test proto file to verify functionality

Fixes precision loss issue for large 64-bit integers in JavaScript.
Large values like 9024037547368883040 lose precision when mapped to number type.
This solution preserves full precision by using string representation.

Tested with:
- Default behavior: normal fields -> number, [jstype = JS_STRING] -> string
- force_int64_string=True: all int64 fields -> string
Copy link

linux-foundation-easycla bot commented Sep 18, 2025

CLA Signed

  • ✅login: theahmadshaikh / name: Ahmad Shaikh / (f903d11)

The committers listed above are authorized under a signed CLA.

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

Successfully merging this pull request may close these issues.

Generated JS files use number for int64 fields, causing wrong values to be sent due to precision loss.
1 participant