Skip to content

Broken emit when Infinity or ‑Infinity ends up in a type position #42905

Description

@ExE-Boss

Bug Report

🔎 Search Terms

  • Infinity
  • NaN
  • numeric
  • literal

🕗 Version & Regression Information

💻 Code

// @declaration
// @showEmit
// @showEmittedFile: index.d.ts

// @filename: index.ts
export const PositiveInfinity: 1e1_000_000 = 1/0 as any;
export const NegativeInfinity: -1e1_000_000 = -1/0 as any;

⏯ Playground Link

Workbench Repro

🙁 Actual behavior

TypeScript emits Infinity and ‑Infinity in a type position, which are intentionally invalid according to #9407 (comment):

// index.d.ts
export const PositiveInfinity: Infinity;
export const NegativeInfinity: -Infinity;

🙂 Expected behavior

The Infinity and ‑Infinity values are valid in a type position, so that the generated .d.ts file is valid.


Also, it’d be nice to support literal NaNs, which would allow for Number.isNaN to be typed as:

interface NumberConstructor {
	isNaN(number: unknown): number is NaN;
}

Related issues

Activity

  1. changed the title [-]Broken emit when `Infinity` or `-Infinity` ends up in a Type position[/-] [+]Broken emit when `Infinity` or `‑Infinity` ends up in a type position[/+] on Feb 21, 2021
  2. MartinJohns commented on Feb 21, 2021

    @MartinJohns
    Contributor

    You're mixing a bug report and a feature request together in one. Fixing the bug would be to emit the type number instead of Infinity. Introducing an Infinity (and NaN) type is a feature request, for which you should provide a good reasoning in response to #9407 (comment).

  3. Jamesernator commented on Feb 22, 2021

    @Jamesernator

    I for one have wanted Infinity/-Infinity as a special case for things that otherwise take BigInts e.g. ranges:

    function* bigintRange(low: bigint, high: bigint | Infinity, step?: bigint=1n): Generator<bigint> {
      for (let i = low; i < high; i += step) {
        yield i;
      }
    }
  4. MartinJohns commented on Feb 22, 2021

    @MartinJohns
    Contributor

    James Browning (@Jamesernator) Just as a general advice: It tremendously helps when you explain your reasoning on why you want this, not just say "I want it for this". In your example you could just as well replace the Infinity with undefined. Having a dedicated Infinity type would not help you in this case, because Infinity would be a sub-type of number, so the union type number | Infinity would be simplified to number. Same as it happens with number | 5.

  5. Jamesernator commented on Feb 22, 2021

    @Jamesernator

    In your example you could just as well replace the Infinity with undefined. Having a dedicated Infinity type would not help you in this case, because Infinity would be a sub-type of number, so the union type number | Infinity would be simplified to number.

    The example is bigint not number. BigInts don't contain an Infinity value, I think it's a lot more readable to use the explicit Infinity value rather than some arbitrary token as it already compares correctly with bigints (e.g. bigint < Infinity is always true, no coercion to Number happens).

  6. ca-d commented on Apr 23, 2021

    @ca-d

    James Browning (@Jamesernator) Just as a general advice: It tremendously helps when you explain your reasoning on why you want this, not just say "I want it for this". In your example you could just as well replace the Infinity with undefined. Having a dedicated Infinity type would not help you in this case, because Infinity would be a sub-type of number, so the union type number | Infinity would be simplified to number. Same as it happens with number | 5.

    More compelling explanations for why these types are needed can be found in #28682 .

  7. typescript-bot commented on Dec 4, 2023

    @typescript-bot
    Contributor

    👋 Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript.


    Issue body code block by ExE Boss (@ExE-Boss)

    ‼️ Exception: Error - error TS5107: Option 'moduleResolution=node10' is deprecated and will stop functioning in TypeScript 7.0. Specify compilerOption '"ignoreDeprecations": "6.0"' to silence this error. Visit https://aka.ms/ts6 for migration information.

    Error: error TS5107: Option 'moduleResolution=node10' is deprecated and will stop functioning in TypeScript 7.0. Specify compilerOption '"ignoreDeprecations": "6.0"' to silence this error.
      Visit https://aka.ms/ts6 for migration information.
    
        at Object.createVirtualTypeScriptEnvironment (/home/runner/work/_actions/microsoft/TypeScript-Twoslash-Repro-Action/master/dist/index.js:8128:11)
        at twoslasher (/home/runner/work/_actions/microsoft/TypeScript-Twoslash-Repro-Action/master/dist/index.js:7618:17)
        at /home/runner/work/_actions/microsoft/TypeScript-Twoslash-Repro-Action/master/dist/index.js:439:44
        at runTwoslashRequests (/home/runner/work/_actions/microsoft/TypeScript-Twoslash-Repro-Action/master/dist/index.js:406:56)
        at run (/home/runner/work/_actions/microsoft/TypeScript-Twoslash-Repro-Action/master/dist/index.js:20096:75)
        at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    

    Historical Information
    Version Reproduction Outputs Time
    4.9.3, 5.0.2, 5.1.3, 5.2.2, 5.3.2

    👍 Compiled
    Emit:

    export declare const PositiveInfinity: Infinity;
    export declare const NegativeInfinity: -Infinity;

    ⚠️ Way slower
  8. lionel-rowe commented on Mar 4, 2025

    @lionel-rowe
    Contributor

    Fixing the bug would be to emit the type number instead of Infinity.

    Wouldn't it be emitting 1e999 or something else that's allowed as a literal TS type but equivalent to IEEE 754 infinity? Emitting number is still wider than the original type.

  9. RyanCavanaugh commented on Sep 6, 2026

    @RyanCavanaugh
    Member

    This is fixed in current native TypeScript 7.1.0-dev.20260906.1. With --declaration --emitDeclarationOnly, TypeScript 4.1.5 and 6.0.3 emit Infinity and -Infinity; consuming the latter reports TS1110 (Type expected).

    Current native TypeScript preserves 1e1_000_000 and -1e1_000_000 in the emitted declaration, which compiles cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: Declaration EmitThe issue relates to the emission of d.ts filesFixedA PR has been merged for this issueHas ReproThis issue has compiler-backed repros: https://aka.ms/ts-repros

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions