TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Arithmetic operations on type-parameters subtyping `bigint` are incorrectly inferred to have type `number`

Open CurtisFenner opened this issue 10 months ago • 0 comments

🔎 Search Terms

bigint, operator, arithmetic, number, subtype, extend, generic, type parameter, incorrect, inference, inferred type, operation, 2365, TS2365

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about arithmetic/bigints/etc

⏯ Playground Link

https://www.typescriptlang.org/play/?target=99&ts=5.8.2#code/GYVwdgxgLglg9mABAIxlAzgUygSTFTAJy2gB4AhNdRTADwLABNrUBzGfAPgAoBDALkSUMAGhSDh6AJSCwIALbIiiAN4AoRJsQB6bYg4FimaPCQxqHYEUKZGiKHEQALXgDdM9gJ4AHDwAM5RSI-REJeKCdlCN4kPzYDPw0tCAR0KH18IhJYBEQAXkReRAAyFABuNSTNXUQAVgA6AA56gCZQzG84QgxEMEcoHw9rLpEqnT1kEHSiwnBYeSHCQi7EOAgIEGJ+MZqAbQBRACVDgF1BAGEYvvT5GFohGFY8aaZViKjB9DEQLBpabwANjAIGhECkwO5iKZqGMbFBNmZMkYTLkALSIACMFQAvpVweg4ADMPUAXBWNxUBhsM8ssYoNwAOxgMS1MBSKQVIA

💻 Code

function bitsetIntersect<Bits extends bigint>(a: Bits, b: Bits): number {
    // intersection is inferred to have type `number` rather than `bigint`
    const intersection = a & b;

    // 5.8.2 reports no type error,
    // but a runtime error occurs:
    // [ERR]: Cannot mix BigInt and other types, use explicit conversions 
    return intersection - 1;
}

console.log(bitsetIntersect(7n, 5n));

🙁 Actual behavior

intersection is inferred to have type number. As a result, no type errors are reported.

When run, the code encounters a TypeError because intersection - 1 attempts to perform arithmetic on a bigint and a number:

[ERR]: Cannot mix BigInt and other types, use explicit conversions

🙂 Expected behavior

intersection should be inferred to have type bigint.

Thus the operation intersection - 1 should report a type error:

Operator '-' cannot be applied to types 'bigint' and 'number'. (2365)

Additional information about the issue

This issue is most likely to be hit when branding bigint, but it could also appear in other situations, such as using subtypes which are unions of literals.


I found some issues that are similar, but have a different scope. These issues were closed as intended, but in these issues, larger type bounds which include bigint but also include number (such as any or bigint | number) are used:

  • #39569
  • #41741
  • #42125
  • #49558
  • #60914

CurtisFenner avatar Mar 15 '25 15:03 CurtisFenner