Skip to content

[email protected] version not fetch global api ? #60924

Closed

Description

@xiaocai-rookie

I use @types/[email protected] version ,but use fetch fail,typescript to me "fetch is not defined"
Could I know , why "fetch is not defined" ?

Activity

  1. mahdi-farnia commented on Jun 23, 2022

    @mahdi-farnia

    I think because it's still experimental
    Also definition for node:readline/promises is not available

  2. xiaocai-rookie commented on Jun 24, 2022

    @xiaocai-rookie
    Author

    I think because it's still experimental Also definition for node:readline/promises is not available

    Yes, node official announce too.

  3. shadow-light commented on Jul 4, 2022

    @shadow-light

    It was simply not added because of time constraints so hopefully sometime soon...

  4. SuperchupuDev commented on Jul 17, 2022

    @SuperchupuDev
    Contributor

    @SimonSchick any chance we can get fetch added anytime soon? it's a really important thing to have in the types

  5. piranna commented on Jul 19, 2022

    @piranna

    Is it available in any branch or development version we can make use of?

  6. piranna commented on Jul 21, 2022

    @piranna

    LOL! Just use vanilla js that solve the problem.

    I would love to, but my client asked me to use Typescript :-)

  7. SimonSchick commented on Jul 21, 2022

    @SimonSchick
    Contributor

    The problem is still that dom libs are not modularized, if they were node typings could just reference dom specs.
    As this time I'd rather not copy & paste the API definitions into node as that could create future liabilities.

  8. piranna commented on Jul 21, 2022

    @piranna

    The problem is still that dom libs are not modularized, if they were node typings could just reference dom specs.
    As this time I'd rather not copy & paste the API definitions into node as that could create future liabilities.

    Agree on that. Can you point us where it's defined so we can copy it ourselves in our projects, meanwhile it get added to Node.js definitions?

  9. mahdi-farnia commented on Jul 21, 2022

    @mahdi-farnia

    I think it's better to not to use fetch Api in node. But if U need it ( for any reason ) it's seems easy to define one:

    declare function fetch(...): ...;
    1. open a new file ( js or ts ) that fetch already available
    2. Command + Click or Ctrl + Click on fetch ( goto definition )
    3. Copy and paste the types to source file

    If you dont wanna see it in your ts files you can just simply create types.d.ts file ( name is important ) or create a folder @types ( name is important ) and put it on that folder

    Note: your d.ts ( definition file ) must not be a module if it is, you have to import the fetch type in every file that you are using it.

  10. piranna commented on Jul 21, 2022

    @piranna

    I think it's better to not to use fetch Api in node

    Why not?

    simply create types.d.ts file

    That's what I'm asking for.

  11. mahdi-farnia commented on Jul 21, 2022

    @mahdi-farnia

    I think it's better to not to use fetch Api in node

    Why not?

    simply create types.d.ts file

    That's what I'm asking for.

    1. It's experimental
    2. Node@18 is not even the LTS version, it's the latest, not the most stable one
  12. piranna commented on Jul 21, 2022

    @piranna

    Not a good code indeed : nodejs/undici

    I would not say @mcollina code is not good, with so much performance obsesive code done...

    But not worst than the microsoft average.
    Good luck for this : https://github.com/nodejs/node/tree/v18.x/lib

    Node.js is not from Microsoft, Microsoft has only developed Typescript on top of it.

  13. piranna commented on Jul 21, 2022

    @piranna
    1. It's experimental

    Good point, fair enough.

    2. Node@18 is not even the LTS version, it's the latest, not the most stable one

    It's the most stable one, just only doesn't have yet the LTS denomination. I could agree that odd versions (v17, v19...) are unstable development versions and should not be used on production, but pair ones (v16, v18) is totally fine.

  14. rjoonas commented on Aug 10, 2022

    @rjoonas
    Contributor

    Yeah, node 18 will be LTS in two months (2022-10-25).

    The problem is still that dom libs are not modularized, if they were node typings could just reference dom specs. As this time I'd rather not copy & paste the API definitions into node as that could create future liabilities.

    @SimonSchick, so are we expecting lib.dom to be modularized before we can add node typings for fetch? Sounds like something that might take a while.

    I wonder if in the meanwhile we could add fetch to types/node by copy-pasting fetch, Request, Response, Headers etc. definitions as a standalone module that would be easy to delete when it's possible to just reference the respective DOM definitions.

  15. piranna commented on Aug 10, 2022

    @piranna

    I wonder if in the meanwhile we could add fetch to types/node by copy-pasting fetch, Request, Response, Headers etc. definitions as a standalone module that would be easy to delete when it's possible to just reference the respective DOM definitions.

    Agree, and add a TODO: comment about that fact, or maybe also store them in an independent types file and reference it from the lib.dom types... starting with the modularization ourselves :-)

  16. 113 remaining items

  17. Qix- commented on Sep 11, 2023

    @Qix-

    Well DT is good for packages that don't have types already but for packages that do, or are otherwise written in TS, DT is usually the worse of the two options due to desynchronization. If there could be a way to extract types at build time, prior to publishing, that'd be the 'ideal' way depending on how you look at things.

  18. piranna commented on Sep 12, 2023

    @piranna

    Prepublish script?

  19. jchitel commented on Sep 28, 2023

    @jchitel

    It seems to me that this points to a fundamental problem with how TypeScript handles type definitions, particularly with global types. The actual TypeScript team should be more involved in this discussion.

    I think the best solution today is to use a clever combination of the lib and types settings within multiple tsconfig files in a single project.

    An example web project might have 3 "environments" that are used by various files: a "web" environment for production code that will run in a browser, a "test" environment that runs in Node (or Deno or Bun) and polyfills web APIs using something like happy-dom or jsdom, and a "server" environment that includes everything running in a regular Node (or Deno or Bun) environment with no web APIs.

    This project can handle the differences in available global APIs and modules by defining 3 separate tsconfig files with explicitly defined lib and types settings:

    • tsconfig.web.json:
      • "lib": ["dom", "dom.iterable", "..."]
      • "types": [] (explicitly declare no types to be included)
      • "include": ["./client"]
      • "exclude": ["./client/**/__tests__"] (exclude tests, which are covered below)
    • tsconfig.node.json:
      • "lib": ["..."] (no DOM APIs are available)
      • "types": ["node"] (explicitly include only Node types)
      • "include": ["./server", "..."] (add whatever other files run in Node, like webpack.config.ts or vite.config.ts)
    • tsconfig.test.json:
      • "lib": ["dom", "dom.iterable", "..."]
      • "types": ["node"] (explicitly include only Node types)
      • "include": ["./client/**/__tests__"] (only include tests)

    This solves most of the problem, notably for files that run only on the web or only in Node. However, the "test" environment has both DOM and Node types. Technically we can't know which fetch types are correct, since any DOM polyfill that is used may or may not overwrite Node's built-in fetch implementation.

    TypeScript's solution for this problem up to this point has been to merge both definitions into one. This works well for interfaces, which will simply accept properties from both definitions. It does not work well for functions, however. We already see this problem with setTimeout. The DOM types return a number, while the Node types return a NodeJS.Timeout. The simple workaround on the web side is to use window.setTimeout, which resolves to only the DOM version. But there is no good solution on the Node side. In the case of setTimeout things typically just happen to work, but if there was a more complicated difference between the types, this would have been a problem ages ago.

    As more and more web APIs are added to non-browser environments, this problem is likely to only get worse. For example, since fetch was designed to work in the browser sandbox, it supports only a subset of HTTP (e.g. no direct access to all cookies), so some environments add additional properties to the options object passed to fetch. Other web APIs are likely to have similar situations.

    We need the ability to more finely tune what an environment looks like, down to selecting individual items from various type definitions. This might be possible using conditional types and Pick and Omit, but those don't really feel "first-class" IMO. I'd like to hear what other people's thoughts are on this.

  20. jchitel commented on Sep 28, 2023

    @jchitel

    The actual TypeScript team should be more involved in this discussion.

    😕

    Oops! I didn't notice that someone from the TypeScript team was already here! I read the earlier comments more thoroughly than the latter ones, so I completely missed your responses. I'm sorry if I offended anyone.

  21. andrewbranch commented on Sep 28, 2023

    @andrewbranch
    Member

    No worries 😄 I think you’ll find some of those links interesting. I think this issue is probably not the best place to go deep into the weeds on rethinking environmental types from the ground up. I broadly agree with you, and this problem used to be very much top-of-mind for me. But from my perspective, each time we’ve hit a wave of global type clashes that seems really intractable, we’ve actually been able to resolve things pretty well with the tools we already have. The PR I have up to add fetch typings, closing this issue, is an example. It’s not perfect but it’s really close, I think. Another one:

    In the case of setTimeout things typically just happen to work

    Again, it’s not perfect, but it doesn’t provide a super strong justification for overhauling the way global types work. We just try our best, through DT contributions, to discourage Node.js-related typings from pulling in the DOM unnecessarily and vice versa, so users can hopefully avoid having @types/node and lib.dom.d.ts in the same compilation, while ensuring they’re written in a way that doesn’t explode into errors when they are in the same compilation. And this continues to mostly work out for most cases.

    I would love to have a more rigorous solution in the future, but it’s definitely not worth holding off on adding fetch while we wait for a silver bullet.

  22. jchitel commented on Sep 28, 2023

    @jchitel

    That makes a lot of sense. The Issues you posted are super interesting and show that others have clearly thought more about this than I have 😅

    I agree that there needs to be a solution right now to resolve this particular issue. I'll defer further discussion to your PR.

  23. joshxyzhimself commented on Oct 5, 2023

    @joshxyzhimself

    For now undici works.

    npm install undici
    import { fetch } from "undici";
  24. andrewbranch commented on Oct 5, 2023

    @andrewbranch
    Member

    #66824 is ready. It only updates v20 typings due to a test infrastructure limitation that will likely be resolved within a couple weeks. I’d like to wait for a non-TS team @types/node maintainer to approve.

  25. thw0rted commented on May 6, 2024

    @thw0rted
    Contributor

    I believe fetch types are pretty good on the latest @types/node@20. Your example looks right to me. You should not need to reference "globalThis" -- just Promise<Response> should typecheck fine -- but it might not be a bad idea if you want to make it very clear that you aren't referring to import { Response } from 'express'.

  26. Jokinen commented on Jul 31, 2024

    @Jokinen

    Apologies for replying to such an old thread, but I am not sure what could be a more suitable place.

    In the introduction of these types there was a workaround that allowed the types to roughly correct for pure node applications and applications with code that should be ran in the browser as well. This combination seems to have become an obstacle in my case.

    I think I am working with a relatively common setup where I have a TS project with code that runs on node and code that runs int he browser (in this case a next application). With such an application lib.dom.d.ts is likely included in the tsconfig, but even if was not, it's not unlikely for it to be pulled in by some dependency. In essence, for this kind of a project it's difficult to get rid of lib.dom.d.ts.

    The presence of lib.dom.d.ts means that the used types are the DOM types. As the original PR states, these are very similar with undici's types. However, there are some difference with one being the omission of the dispatcher field. This field can be use to set a custom agent, which allows custom keepalive settings to be configured.

    I've used a better part of the day trying to find the best workaround, but it seems that there are quite a few potholes that can be struck. For instance, importing fetch directly from undici breaks interop with msw.

    Ultimately I was able to work around the limitation by using two tsconfig files and tinkering with the settings and project structure until I was able isolate our node fetch integration from lib.dom.d.ts.

  27. thw0rted commented on Jul 31, 2024

    @thw0rted
    Contributor

    Do you have an example of the code that wasn't working in the mixed environment (Node code, with lib-dom included)? I'm wondering if some selective type-casting could have saved you the trouble of multiple tsconfig files. That's probably a good long-term solution, though.

  28. Jokinen commented on Aug 16, 2024

    @Jokinen

    @thw0rted Thank you for the reply. I ended up iterating and did end up going the route you suggested. I ended up installing undici-types and type cast in a few places in order to get the types to cooperate. We have a wrapper on top of the fetch API which made the process easier.

    All global types were browser types so whenever we attempted to use node-only-features, we'd have issues. In our case the problem case was adding a dispatcher that changed the default keepalive settings.

    fetch('https://example.com', {
      // ...options
      dispatcher: const customKeepAliveAgent = new undici.Agent({
        // customs settings
      });,
    });

    I can also vouch that it doesn't feel like a good long-term solution. As we've implemented more functionality to our fetch wrapper, we've come across type issues consistently. In time we'll likely find a better balance in casting and we'll have fewer issues.

    The type inconsistencies can be difficult to reason about if you aren't aware of the limitations of the type system. For instance, we ended up breaking instanceof URL checks. I assume it's due to a type cast that's not optimal. Likely we've cast a RequestInfo to be a Undici.RequestInfo (e.g. string | node:url.URL | Undici.Request. When we make the comparison TS sees the URL in instanceof URL to be a browser.URL. It basically results in a scenario like this:

    export const getUrl = (url: Undici.RequestInfo) => {
      if (typeof url === 'string') {
        return url;
      } else if (url instanceof URL) {
        return url.href;
      }
    
      // @ts-expect-error: TS errors because field 'url' does not exist in 'URL'
      return url.url;
    };

    Can be dealt with by using another cast, but things of this nature tend to pop up while developing.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions