BigInt 类型在从十进制转换为十六进制时不维护

问题描述

我有一些包含大量数字的数据,这些数据我读入并存储为字符串。我需要将它们转换为十六进制字符串,但是当我尝试使用 BigInt(decimalString).toString(16) 时,由于仍然截断了十六进制值的最后一个字符,因此不会保留 bigInt 类型。

const decimal = '18446744072635809797'
console.log(decimal)
// Expected: 18446744072635809797 Actual: 18446744072635810000 FAIL

console.log(BigInt(decimal))
// Expected: 18446744072635809792n Actual: 18446744072635809792n SUCCESS

console.log(BigInt(decimal).toString(16))
// Expected: ffffffffc0000005 Actual: "ffffffffc0000000 FAIL

最奇怪的部分是在 JSfiddle 中尝试相同的代码完全按预期工作,但在我的环境中却没有。这是我的 tsconfig

{
    "compilerOptions": {
     "target": "ES5","lib": ["dom","dom.iterable","esnext","ESNext.BigInt"],"allowJs": true,"skipLibCheck": true,"esModuleInterop": true,"allowSyntheticDefaultImports": true,"strict": true,"forceConsistentCasingInFileNames": true,"noFallthroughCasesInSwitch": true,"module": "esnext","moduleResolution": "node","resolveJsonModule": true,"isolatedModules": true,"noEmit": true,"jsx": "react-jsx"
    },"include": ["src"]
}

我发现浏览器(Edge 和 Chrome)之间也发生了相同的行为。我错过了什么?

json文件基本上是这样的 { 一:18446744072635809797 } 我使用接口将其保存到 javascript 对象以将其转换为字符串:

interface IData{
  a: string
}

service.GetData().then((data: IData) => {
  if(data.a > Number.MAX_SAFE_INTEGER){
    const decimal = BigInt(data.a)
    // attempt to convert decimal to hex
  }
})

解决方法

json文件基本上是这样的{ a: 18446744072635809797 }

那是你的问题:值是一个数字,并被解析为一个数字。 JSON 应该是 { a: "18446744072635809797" },然后您可以通过将此字符串传递给 BigInt 函数来获得您期望的行为,例如BigInt(data.a).toString(16)

TypeScript 接口定义不会导致执行任何转换。即使是这样,当 JSON.parse 返回时也已经太晚了,因为无法存储在 Number 中的位在那时已经丢失了。

亲眼看看:

> JSON.parse('{ "a": 18446744072635809797 }')
← {a: 18446744072635810000}
> JSON.parse('{ "a": "18446744072635809797" }')
← {a: '18446744072635809797'}