Skip to content

Preserve source text for negative numeric literals in declaration emit#4158

Draft
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-negative-numeric-const-literals
Draft

Preserve source text for negative numeric literals in declaration emit#4158
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-negative-numeric-const-literals

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jun 1, 2026

Declaration emit normalized negative numeric const literals to their canonical JS-number form instead of preserving the authored text:

export const a = -1e500 as const;
export const b = -123456789012345678901234567890 as const;
// Before                          // After (matches tsc)
export declare const a: -Infinity;                       export declare const a: -1e500;
export declare const b: -1.2345678901234568e+29;         export declare const b: -123456789012345678901234567890;

The scanner stores the canonical form as a numeric literal's text. On the negative (PrefixUnaryExpression) as const path, node reuse clones the operand and detaches it from its source file, so the printer can no longer recover the original text.

Changes

  • reuseNegativeNumericLiteralType (pseudotypenodebuilder.go) — rebuilds the operand of a negated numeric literal from the original source via scanner.GetSourceTextOfNodeFromSourceFile. Skips invalid/separator literals and bigints, mirroring the printer's canUseOriginalText rules.
  • inReusedLiteralCollection flag (NodeBuilderImpl) — set while serializing object/tuple members so nested literals retain the canonical form.
  • Compiler test — added testdata/tests/cases/compiler/declarationEmitNegativeNumericLiteralAsConst.ts with accepted .js, .symbols, and .types baselines covering the full behavior matrix below.

Behavior matrix (verified against built submodule TypeScript 6.0.0)

Case Result
Top-level negative numeric (-1e500, -0xFF, -1e3) original source text
Positive numeric (1e31000, 0xFF255) canonical (unchanged)
Nested in object/array ([-1e500] as const) canonical -Infinity (unchanged)
BigInt (-0xFFn) canonical (unchanged)
Numeric separator (-1_000) canonical -1000 (unchanged)

The asymmetry (top-level source vs. nested canonical) intentionally matches tsc, which canonicalizes literals nested inside reused object/tuple as const types regardless of inner assertions.

…aration emit

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix declaration emit for negative numeric const literals Preserve source text for negative numeric literals in declaration emit Jun 1, 2026
Copilot AI requested a review from jakebailey June 1, 2026 18:47
@jakebailey
Copy link
Copy Markdown
Member

@copilot no test??

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 1, 2026

@copilot no test??

Added a compiler test in 6da6... — testdata/tests/cases/compiler/declarationEmitNegativeNumericLiteralAsConst.ts with baselines covering the full behavior matrix: top-level negative numerics preserve source text (-1e500, -123456789012345678901234567890, -0xff, -1e3), positive numerics stay canonical (1e31000, 0xff255), and nested/bigint/separator cases keep their canonical form.

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.

Declaration emit differs for negative numeric const literals

2 participants