Skip to content

Emit plain .d.ts for libraries with outputExtensions (TS 7 nightly 20261014) - #41

Draft
NullVoxPopuli wants to merge 4 commits into
mainfrom
nvp/output-extensions
Draft

NullVoxPopuli wants to merge 4 commits into
mainfrom
nvp/output-extensions

Conversation

@NullVoxPopuli

@NullVoxPopuli NullVoxPopuli commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Important

Still blocked. Two upstream problems remain on 7.1.0-dev.20261015.1. See "Before this can continue" below.

Libraries can now emit counter.d.ts instead of counter.d.gts.ts, so declarations/ matches dist/ file for file. This uses the new outputExtensions option from microsoft/TypeScript#64581, which fixes microsoft/TypeScript#64053.

Changes

  • examples/cli-library-v2: sets outputExtensions: { ".gts": ".js", ".gjs": ".js" } and rewriteRelativeImportExtensions: true. The emitted index.d.ts now says from './components/counter.js', and the ./* → ./declarations/*.d.ts export works for every module. I removed the README note saying it didn't.
  • README: new "Publishing a library" section. MIGRATING_FROM_TS6.md links the #64053 item to it.
  • Test: a new declaration-output-extensions fixture checks that Greeting.d.ts is emitted and Greeting.d.gts.ts is not.
  • Bumps every TS 7 pin from 7.1.0-dev.20260821.1 to 7.1.0-dev.20261014.1.

Why the mapper's package.json doesn't set a default

typescript.contentMapper.outputExtensions can go in the mapper's package.json, but I didn't add it:

  • Any outputExtensions requires rewriteRelativeImportExtensions. Without it, tsc reports TS18120, even with --noEmit.
  • With the flag on, both example apps fail with TS2877. Their extension imports aren't relative (#app/..., cli-app/...), so they can't be rewritten.
  • So a default would break every app on upgrade. Apps could opt out with "outputExtensions": {}, but libraries are the ones that emit.

The other manifest fields don't help either: compilerOptions only lists which options get forwarded to the mapper. It can't set them.

Before this can continue

Now on 7.1.0-dev.20261015.1 (second commit). Two problems remain.

@extends over Component.extend(Mixin)

microsoft/TypeScript#64072 applies the tag's type arguments to the call's return type. Ember's Component.extend(Evented) returns a constructor that is not generic.

Go-to-definition on a .gts import specifier

test/lsp.js "go to definition from a .ts import into a .gts module" fails.

The outputExtensions work itself is done.

Tracking: #23

🤖 Generated with Claude Code

TypeScript 7.1.0-dev.20261014.1 adds `outputExtensions` to content mapper
entries (microsoft/TypeScript#64581, fixing #64053). The library example
opts in, so counter.gts emits counter.d.ts and declarations/ matches dist/.

- Bump the TypeScript 7 nightly to 7.1.0-dev.20261014.1.
- Document "Publishing a library" in the README and point the migration
  guide at it.
- Add a declaration-output-extensions fixture and test.

The mapper's package.json does not set a default: apps would then need
rewriteRelativeImportExtensions, which reports TS2877 for non-relative
extension imports such as #app/components/counter.gts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

🏎️ Benchmark Comparison

Benchmark Control (p50) Experiment (p50) Δ Noise
⚪ transform 363.94 ms 362.04 ms -0.5% ±5.5%
⚪ server 8-in-flight 393.38 ms 373.87 ms -5.0% ±9.1%
⚪ tsc total 1736.00 ms 1686.00 ms -2.9% ±3.6%
⚪ tsc mapper wait 1723.00 ms 1672.00 ms -3.0% ±3.1%

🟢 faster · 🔴 slower · 🟠 slightly slower · ⚪ within 2% or within round-to-round noise

Full mitata output
clk: ~4.34 GHz
cpu: AMD EPYC 9V45 96-Core Processor
runtime: node 24.21.0 (x64-linux)

benchmark                   avg (min … max) p75 / p99    (min … top 1%)
------------------------------------------- -------------------------------
transform (control)          418.61 ms/iter 462.45 ms   █                  
                    (346.27 ms … 541.84 ms) 541.28 ms   ██   █             
                    (844.17 kb …  71.91 mb)  43.10 mb █████▁██▁▁▁▁█▁█▁█▁▁▁█

server 8-in-flight (control) 405.24 ms/iter 412.69 ms        █   █         
                    (382.31 ms … 440.05 ms) 434.64 ms  █     █   █         
                    (  9.68 mb …   9.79 mb)   9.74 mb ████▁▁▁█▁▁▁████▁▁▁▁▁█

━━━ round 1/3: mapper experiment (core 2) ━━━

clk: ~4.33 GHz
cpu: AMD EPYC 9V45 96-Core Processor
runtime: node 24.21.0 (x64-linux)

benchmark                      avg (min … max) p75 / p99    (min … top 1%)
---------------------------------------------- -------------------------------
transform (experiment)          376.57 ms/iter 387.81 ms  █                   
                       (343.59 ms … 490.07 ms) 412.98 ms  ██  █     █ █       
                       (  2.71 mb …  61.64 mb)  42.82 mb ███▁▁██▁▁▁▁█▁█▁▁▁▁█▁█

server 8-in-flight (experiment) 382.51 ms/iter 400.90 ms   █   █             █
                       (339.41 ms … 441.10 ms) 425.52 ms ▅ █ ▅▅█ ▅ ▅ ▅▅▅▅    █
                       (  9.68 mb …   9.78 mb)   9.74 mb █▁█▁███▁█▁█▁████▁▁▁▁█

━━━ round 1/3: tsc control ━━━

tsc: 36 files (6 fixtures × 6), 3 runs after warm-up
  run 1: total 1.83s, mapper wait 1.81s
  run 2: total 1.74s, mapper wait 1.72s
  run 3: total 1.71s, mapper wait 1.69s
  p50: total 1.74s, mapper wait 1.72s

━━━ round 1/3: tsc experiment ━━━

tsc: 36 files (6 fixtures × 6), 3 runs after warm-up
  run 1: total 1.75s, mapper wait 1.74s
  run 2: total 1.72s, mapper wait 1.70s
  run 3: total 1.69s, mapper wait 1.68s
  p50: total 1.72s, mapper wait 1.70s

━━━ round 2/3: mapper control (core 2) ━━━

clk: ~4.37 GHz
cpu: AMD EPYC 9V45 96-Core Processor
runtime: node 24.21.0 (x64-linux)

benchmark                   avg (min … max) p75 / p99    (min … top 1%)
------------------------------------------- -------------------------------
transform (control)          368.02 ms/iter 375.42 ms     ██     █         
                    (346.03 ms … 402.27 ms) 401.25 ms ▅▅▅ ██▅▅ ▅▅█  ▅     ▅
                    (428.09 kb …  72.71 mb)  39.74 mb ███▁████▁███▁▁█▁▁▁▁▁█

server 8-in-flight (control) 379.23 ms/iter 393.90 ms █     █              
                    (350.06 ms … 411.91 ms) 406.15 ms █▅ ▅▅ █   ▅ ▅ ▅▅▅ ▅▅▅
                    (  9.67 mb …   9.96 mb)   9.76 mb ██▁██▁█▁▁▁█▁█▁███▁███

━━━ round 2/3: mapper experiment (core 0) ━━━

clk: ~4.39 GHz
cpu: AMD EPYC 9V45 96-Core Processor
runtime: node 24.21.0 (x64-linux)

benchmark                      avg (min … max) p75 / p99    (min … top 1%)
---------------------------------------------- -------------------------------
transform (experiment)          366.15 ms/iter 371.85 ms       █     █        
                       (334.89 ms … 399.48 ms) 395.99 ms ▅ ▅▅  █▅▅▅▅▅█   ▅  ▅▅
                       (  3.27 mb …  68.09 mb)  39.77 mb █▁██▁▁███████▁▁▁█▁▁██

server 8-in-flight (experiment) 401.99 ms/iter 413.48 ms            ██    █   
                       (362.75 ms … 432.66 ms) 423.93 ms ▅  ▅    ▅▅ ██▅ ▅▅█▅ ▅
                       (  9.68 mb …   9.81 mb)   9.74 mb █▁▁█▁▁▁▁██▁███▁████▁█

━━━ round 2/3: tsc experiment ━━━

tsc: 36 files (6 fixtures × 6), 3 runs after warm-up
  run 1: total 1.68s, mapper wait 1.67s
  run 2: total 1.72s, mapper wait 1.70s
  run 3: total 1.68s, mapper wait 1.66s
  p50: total 1.68s, mapper wait 1.67s

━━━ round 2/3: tsc control ━━━

tsc: 36 files (6 fixtures × 6), 3 runs after warm-up
  run 1: total 1.67s, mapper wait 1.66s
  run 2: total 1.72s, mapper wait 1.70s
  run 3: total 1.72s, mapper wait 1.70s
  p50: total 1.72s, mapper wait 1.70s

━━━ round 3/3: mapper control (core 0) ━━━

clk: ~4.19 GHz
cpu: AMD EPYC 9V45 96-Core Processor
runtime: node 24.21.0 (x64-linux)

benchmark                   avg (min … max) p75 / p99    (min … top 1%)
------------------------------------------- -------------------------------
transform (control)          365.11 ms/iter 371.45 ms   █    █    █        
                    (343.46 ms … 402.48 ms) 383.87 ms ▅▅█    █ ▅▅▅█ ▅ ▅ ▅ ▅
                    (272.66 kb …  59.44 mb)  39.08 mb ███▁▁▁▁█▁████▁█▁█▁█▁█

server 8-in-flight (control) 391.25 ms/iter 405.89 ms          █        █  
                    (356.59 ms … 413.15 ms) 410.84 ms          █       ██  
                    (  9.68 mb …   9.79 mb)   9.75 mb ██▁█▁▁▁▁▁█▁▁▁██▁▁████

━━━ round 3/3: mapper experiment (core 2) ━━━

clk: ~4.18 GHz
cpu: AMD EPYC 9V45 96-Core Processor
runtime: node 24.21.0 (x64-linux)

benchmark                      avg (min … max) p75 / p99    (min … top 1%)
---------------------------------------------- -------------------------------
transform (experiment)          366.61 ms/iter 378.74 ms          █           
                       (333.15 ms … 407.16 ms) 399.24 ms       █  ██          
                       (  5.33 mb …  70.56 mb)  42.38 mb █▁▁█▁▁█████▁▁▁███▁▁▁█

server 8-in-flight (experiment) 369.80 ms/iter 383.32 ms  █                   
                       (348.05 ms … 399.88 ms) 393.23 ms ██               █   
                       (  9.69 mb …   9.86 mb)   9.75 mb ██▁▁▁▁███▁█▁█▁▁███▁▁█

━━━ round 3/3: tsc control ━━━

tsc: 36 files (6 fixtures × 6), 3 runs after warm-up
  run 1: total 1.78s, mapper wait 1.76s
  run 2: total 1.69s, mapper wait 1.67s
  run 3: total 1.78s, mapper wait 1.76s
  p50: total 1.78s, mapper wait 1.76s

━━━ round 3/3: tsc experiment ━━━

tsc: 36 files (6 fixtures × 6), 3 runs after warm-up
  run 1: total 1.70s, mapper wait 1.68s
  run 2: total 1.66s, mapper wait 1.65s
  run 3: total 1.69s, mapper wait 1.67s
  p50: total 1.69s, mapper wait 1.67s

@NullVoxPopuli
NullVoxPopuli marked this pull request as ready for review October 14, 2026 22:33
@NullVoxPopuli
NullVoxPopuli marked this pull request as draft October 14, 2026 22:33
This nightly includes microsoft/TypeScript#64072 (the #64058 fix). It
applies the JSDoc @extends type arguments to the call's return type, so
over Component.extend(Evented), which returns a constructor that is not
generic, the error changes to TS2508 and the signature is still lost.
Update the upstream-differences snapshot and docs to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NullVoxPopuli and others added 2 commits October 15, 2026 11:28
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

content-mapper generates inconsistent declaration extensions, making management of package.json#exports hard / verbose

1 participant