Skip to content

Easy/important feature: Make deno types output for JSR/npm packages as well as deno's own types #33290

@izelnakri

Description

@izelnakri

Hi there,

Recently I built the best JS/Testing tool in the world/history, I'm not joking (seriously): https://github.com/izelnakri/qunitx

However during its build process to make deno work with it without any configuration, I realized deno cli deno types command misses an important feature that is probably easy to implement. On build.ts of this library I generate a dist folder that I publish to npm so deno can use an npm package that has jsr imports in it and by-passing jsr limitations of deno when running an npm package. However I hardcoded some of the type definitions of the jsr packages so deno doesn't warn when people use this package with deno: https://github.com/izelnakri/qunitx/tree/main/shims/deno/vendor-types

I think this feature is rather easy to implement by passing its references to deno types:

$ deno types "jsr:@std/testing/bdd"
# => outputs the types to stdout, maybe --write and --ignore-subdependencies or --depth arguments would be nice addition too

Thanks for your consideration!

Also I'm attaching the LLM response to my issue so you might understand that this is a legit concern, not a wrong assumption or NOT a LLM generated hallucinated issue/feature request:

#-> On Claude Code:

❯ - Shouldnt shims/deno/vendor-types folder be generated by deno?

  Searched for 2 patterns, read 4 files, listed 1 directory (ctrl+o to expand)

● Yes and no — it depends on the toolchain. The vendor-types folder is there for tsc (via tsconfig.json), not for Deno.

  Deno resolves jsr:@std/testing/bdd and jsr:@std/assert natively with full types from JSR. It doesn't need that folder at all.

  The problem is tsc doesn't understand jsr: specifiers. When tsconfig.json compiles shims/deno/**/*.ts, it can't resolve those imports, so the hand-written .d.ts stubs in
  vendor-types tell tsc what those modules look like.

  So the folder is essentially a shim-for-a-shim: minimal ambient module declarations so tsc doesn't choke on JSR imports when building dist/.

  Could Deno generate it? Not directly in this form. deno vendor downloads actual source files (not ambient .d.ts declarations), and deno types only outputs Deno's own built-in API
   types — not JSR package types. You'd need a custom script to turn vendored JSR source into ambient module stubs.

  The practical options are:
  1. Keep it as-is — hand-written stubs are minimal and stable (JSR std API doesn't change often)
  2. Exclude shims/deno/ from tsc — let Deno handle its own type-checking separately via deno check, remove the stubs entirely
  3. Use path aliases in tsconfig.json — map jsr:@std/... to vendored source paths

  Option 2 is the cleanest if the goal is to remove the manual maintenance burden.

✻ Worked for 39s

※ recap: Discussing whether shims/deno/vendor-types should be generated by Deno. It's hand-written for tsc compatibility since tsc can't resolve jsr: specifiers. No action pending
  — waiting for user direction. (disable recaps in /config)

❯ How would "Option 2" look like? Does it generate more complexity or is a definite improvement?

  Read 2 files, listed 2 directories (ctrl+o to expand)

● After reading build.ts, Option 2 is not a clean improvement for this codebase. Here's why:

  tsc does two jobs for shims/deno/:

  1. Type-checking — catching errors at build time
  2. Declaration generation — producing dist/deno/*.d.ts which npm consumers rely on (including fixDenoIndexDts() which patches that output)

  Excluding shims/deno/ from tsc breaks job #2. You'd lose dist/deno/index.d.ts, module.d.ts, and test.d.ts. Those aren't optional — they're published in dist/ and consumed by
  TypeScript users who install the package from npm.

  To recover declaration generation you'd need one of:
  - A separate tsconfig.deno.json just for deno — same stubs, just isolated. Adds a config file, doesn't remove vendor-types/
  - Hand-write dist/deno/*.d.ts — strictly worse
  - A custom dts-generation script — more code to maintain than 3 stub files

  deno check handles type-checking natively, but Deno has no --declaration emit flag.

  Bottom line: the current approach is already the simplest working solution. The vendor-types/ folder is 3 small files (< 30 lines total) that bridge one toolchain gap. Option 2
  saves nothing — it just moves the complexity elsewhere while adding a build-step coordination problem.

  The only real argument for changing it would be if the JSR stubs become a maintenance burden as the API evolves, but jsr:@std/testing/bdd and jsr:@std/assert are stable enough
  that this is unlikely to matter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions