Skip to content

Support having '@types/web' as overriding 'dom' in TypeScript's lib resolver #44795

Closed

Description

@orta

Suggestion

I'd like to be able to install @types/web and have the following happen:

  • Other dependencies (like from DT) using something like /// <reference lib="dom"> do not resolve to the vendored libdom.d.ts
  • The default inclusion of dom in a project via lib would automatically pick up @types/web (or be fully suppressed)

🔍 Search Terms

dom types/web web lib

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • x ] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

  1. Hardcode some sort of dom -> @types/web inside the TS compiler's
  2. Support some kind of pragma in @types/web

1 - Hardcoding

Pros:
@types/web is a special case (though there could be more in the future) and this could be the smallest possible change.

Cons:
It feels a bit meh.

2 - Pragmas

Pros:
We have existing pragmas: /// <reference no-default-lib="true"/> for type of thing. This answer is totally generic and would allow others to have their own implementations of other deployed libs.

Cons:
I'd need to check, but this might mean looking for the pragmas across all Types (@types) dts files before we can reliably use the files inlib

Activity

  1. MartinJohns commented on Jun 29, 2021

    @MartinJohns
    Contributor

    With the pragma approach, what would happen if two packages aim to replace the definitions? This could easily happen with unfortunate dependencies.

    A third option may be to have it explicitly configured in the tsconfig.json. I'm the last person who'd ask for yet another flag / option, but it sounds sensible for this. This would allow replacement of any library file, and it's explicit (no magic).

  2. orta commented on Jun 29, 2021

    @orta
    ContributorAuthor

    Great thinking Martin Johns (@MartinJohns)

    Nathan Shively-Sanders (@sandersn) was interested in having modules in lib for other reasons I think, I wonder if could be solved with the same concept:

    {
      compilerOptions: {
        lib: ["es2015", { name: "dom", module: "@types/web" }]
      }
    }
  3. MartinJohns commented on Jun 29, 2021

    @MartinJohns
    Contributor

    Nathan Shively-Sanders (@sandersn) was interested in having modules in lib for other reasons I think

    What are the reasons? You didn't fill out the "Motivating Example" and "Use Cases" sections of the issue template. :-P

  4. orta commented on Jun 29, 2021

    @orta
    ContributorAuthor

    Chatted with wes (and I've marked this issue for design review tomorrow) but I'm mostly pretty convinced that a pragma is the right route here now that I understand that we basically read all the visible source-code before adding lib to a compile for type checking. So the cons for 2 don't apply.

    I personally think if we hit a dupe we should throw, but realistically they would probably raise an error due to duplicated types anyway. Will see what happens at the language review meeting.

  5. DanielRosenwasser commented on Jul 2, 2021

    @DanielRosenwasser
    Member

    I might've missed some other context that was already discussed, but I don't think a pragma on its own is the right solution. Over time, .d.ts files getting published that say "no no no, let me tell you what to load" end up falling in conflict with what the end-user wants.

    I personally think if we hit a dupe we should throw,

    If we do end up shipping another pragma that seems reasonable, but it means we have to think about how a user can put their foot down and say exactly what gets loaded. The benefit of that is that you can give an error message saying "these two libraries conflict in what they're asking for".

    I think ultimately, TypeScript users need to be able to control the environment that gets checked, and tsconfig.json needs to allow controlling that.

  6. DanielRosenwasser commented on Jul 2, 2021

    @DanielRosenwasser
    Member

    Another thing to consider: what is the right way to declare a dependency on @types/web if you're a library? peerDependency?

  7. orta commented on Aug 19, 2021

    @orta
    ContributorAuthor

    I think this syntax makes it very explicit what is going on:

    {
      compilerOptions: {
        lib: ["es2015", { replace: "dom", with: "@types/web" }]
      }
    }

    However it brings its own problems, because there's a question of how should this act:

    {
      compilerOptions: {
        lib: [{ replace: "dom", with: "@types/web" }]
      }
    }

    Should it act like: lib: [] or lib: undefined?

    I think it should probably act like: lib: [] - but it'll need documenting somewhere.

  8. orta commented on Sep 17, 2021

    @orta
    ContributorAuthor

    #45771 shipped this into the TypeScript 4.5 - the answer was to leave dependency managers to handle the resolution

    This answer to supporting your own versions of in-built libraries uses the node_modules resolution structure to let you define libraries. The path lookup looks like:

    • lib.dom.d.ts -> @typescript/dom
    • lib.dom.iterable.d.ts -> @typescript/dom/iterable
    • lib.es2015.symbol.wellknown.d.ts -> @typescript/es2015/symbol-wellknown

    If you made a package which just sets up @typescript/es2015/symbol-wellknown.d.ts without @typescript/es2015/index.d.ts, then es2015 would still resolve to the TypeScript hosted version.

    All JS dependency managers support this syntax:

    {
      "dependencies": {
        "@typescript/dom": "npm:@types/web"
      }
    }
    
  9. alfaproject commented on Feb 22, 2022

    @alfaproject

    Orta Therox (@orta) is there documentation for this? I'd like to have some DOM types like top level URLSearchParams in node applications but I don't want to add dom to libs. I'd like to only have whatever node version X supports.

    I'm wondering if this would be the way to do it or I'm looking at the wrong place

  10. orta commented on Feb 22, 2022

    @orta
    ContributorAuthor

    You'd need to add the types you want to your own .d.ts file which affects global scope, it's not related to this feature

  11. alfaproject commented on Feb 22, 2022

    @alfaproject

    We have the right node types and types: ["node"] which works for everything except for these shared browser globals, so I need to also add libs: ["dom"] to access these globals which are also available in node.

    I thought this feature was going to enable to skip the libs: ["dom"] under these circumstances because I was under the impression that the node types don't have these globals because it conflicts with the bundled dom ones?

    I'm sorry if this is really off-topic but I seem to be missing something obvious here o:

  12. orta commented on Feb 23, 2022

    @orta
    ContributorAuthor

    This feature lets you replace the lib files which ship with TypeScript in your projects. You could replace the dom lib with your custom subset but that's overcomplicating things when you can instead add the file to your project and not import the default dom at all.

  13. alfaproject commented on Feb 23, 2022

    @alfaproject

    So, no matter what, I need some form of dom instead of having the correct node types with all the available node globals? Alright, I guess. Seems a bit awkward but thanks for your guidance

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

    SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions