Protobuf在TypeScript中的64位长整型精度问题

一直以来,在 JavaScript 中表示数值的只有 Number 这种以 64 位浮点形式存储的类型, 是不存在类似 Long 这种64位的长整形,这就会造成后端传输来的长整型数据到了前端出现精度丢失的情况:

let n1 = 177777777777777777;
console.log(n1) // 177777777777777800

遗憾的是在 TypeScript 中也没有 Long 这样的长整型,但是 Node.JS 中的,有许多十分优秀的 modules ,其中 long这个第三方 module 使用了一个 class ,封装了两个 32 bit 有符号 number 类型与一个表示有无符号的布尔类型 , 完美的解决了这个问题.

在使用 Protobuf 时, Protobuf 中存在 int64,sint64,uint64,fixed64,sfixed64这样的类型,这在 LP64 类型操作系统中,明显是会占用长达 64 bit 的连续空间,因此可以引入 long这个模块解决此问题:npm install long.

TypeScript 使用 Protbuf 需要先安装 protobufjs,使用其中的 pbjspbts,使用命令npm install protobufjs -g 安装引入系统路径即可.

先执行pbjs生成 js 文件:

pbjs -t static-module -w es6 --force-long -o file.js file1.proto file2.proto file3.proto

其中-t static-module 参数是生成无反射的静态代码,这是因为需要导入 TypeScript 中; -w es6参数则是开启 ES6 标准语法生成代码,--force-long则是代表用Long型替换 protobuf 中的 s-/u-/int64 和 s-/fixed64 类型.

然后执行pbts生成 ts 文件:

pbts -o file.d.ts file.js

这里需要注意,因为之前使用了--force-long参数,会在代码中出现 Long 类型. 这时,直接引用此 ts 文件时将会报无法识别的错误,因此需要在pbts生成的 ts 文件的行首加入:

import * as Long from "long/index";

让其引入 long 模块,这就可以完美的使用 protobuf 生成的数据结构了.