14

In the console, when running node --experimental-fetch the fetch command is now natively enabled (node version >=17.6). see below

native fetch with node

However, when I add a typescript layer, I always get error TS2304: Cannot find name 'fetch'.

how can I solve this?

background idea: use fetch natively and get rid of node-fetch and @types/node-fetch dependencies

tsconfig.json and general setup: https://github.com/nexys-system/server-boilerplate/blob/master/tsconfig.json

see also:

John
  • 4,786
  • 8
  • 35
  • 44
  • 1
    Given that it's experimental it's presumably not yet in `@types/node`. – jonrsharpe Feb 28 '22 at 11:24
  • can I create a PR in `@types/node`? Any other way I can hack my way around it? i.e. define `fetch` globally or so? – John Feb 28 '22 at 11:25
  • 1. Yes, you can create a PR on the DefinitelyTyped repo where those types are defined. 2. Yes you can also declare additional global types, see e.g. https://stackoverflow.com/a/43523944/3001761. – jonrsharpe Feb 28 '22 at 11:28
  • I made it work, here's a sample repo: https://github.com/nexys-system/node-koa-fetch: PRs and suggestions welcome – John Mar 02 '22 at 10:23
  • 3
    As a hacky workaround, you can extend your `lib` section in `tsconfig.json` with `"dom"`. This includes the types for `fetch` but also a lot of other built-ins that are available only in browser, so be careful. – Tyrrrz Apr 20 '22 at 13:53
  • 2
    Hey, I'm still having trouble with this. I'm on node 18.9.0 with the latest `@types/node` (18.7.18) and it's still giving me the "Cannot find name 'fetch'" error. I'm targeting es2022 in my tsconfig file and including node types. Interestingly, a quick search through the @types/node package shows there is no fetch defined.... Am I missing something? – kael Sep 16 '22 at 16:04
  • @kael actually it worked for me because Dom was enabled. Without it i think it still fails :/ – John Sep 17 '22 at 17:20

3 Answers3

15

Please don't import the whole lib dom from the typescript package or add the node-fetch package for types as some people do. Cause ...

  1. Importing lib dom adds a lot of things to your globals that aren't available in node environments.
  2. Adding the node-fetch to your project only for types, adds only the required types, but sadly they aren't complaint to the W3C fetch() specs. See: https://github.com/node-fetch/node-fetch/blob/main/docs/v3-LIMITS.md

What is somehow correct indeed, is to import the package "undici". As this package is the base for node's fetch() implementation, it provides the correct types. Source: https://nodejs.org/de/blog/announcements/v18-release-announce/#fetch-experimental

I recommend adding a .d.ts file to your project, with the following content:

import * as undici_types from 'undici';

declare global {
  export const {
    fetch,
    FormData,
    Headers,
    Request,
    Response,
  }: typeof import('undici');

  type FormData = undici_types.FormData;
  type Headers = undici_types.Headers;
  type HeadersInit = undici_types.HeadersInit;
  type BodyInit = undici_types.BodyInit;
  type Request = undici_types.Request;
  type RequestInit = undici_types.RequestInit;
  type RequestInfo = undici_types.RequestInfo;
  type RequestMode = undici_types.RequestMode;
  type RequestRedirect = undici_types.RequestRedirect;
  type RequestCredentials = undici_types.RequestCredentials;
  type RequestDestination = undici_types.RequestDestination;
  type ReferrerPolicy = undici_types.ReferrerPolicy;
  type Response = undici_types.Response;
  type ResponseInit = undici_types.ResponseInit;
  type ResponseType = undici_types.ResponseType;
}

This obviously requires you to install the package 'undici' as well via your package manager of choice! https://www.npmjs.com/package/undici

For the ones super interested in this, there is a discussion ongoing in the DefinitelyTyped repository on github about it: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/60924

Ruben
  • 390
  • 4
  • 6
  • thanks! do you know when we can expect this to be part of typescript OOTB? – John Mar 09 '23 at 18:42
  • You're welcome. Sadly not. People expecting it to be added, as soon as node does not consider this feature experimental anymore. – Ruben Mar 10 '23 at 19:20
  • 1
    This helped greatly, I was originally going down the path of including the `"@types/node-fetch": "^2.6.2",`, everything coded out right, however when I went to run the code I was hit with missing module for `node-fetch`. Dropping the `@types/node-fetch` and removing the imports from my .ts files along with this above solution got me back on track, thanks. I'm currently running with node: v18.15.0 package.json: "@types/node": "^18.15.3" tsconfig.json lib: ["ES2020"] Once the @types/node package contains the types for fetch I can then remove this temporary .d.ts file. – Bogus Hawtsauce Mar 18 '23 at 15:38
  • 1
    Another note, I did not have to install the undici package, as node has it included already in my current version v18.15.0 – Bogus Hawtsauce Mar 18 '23 at 15:45
13

There are only 2 ways at the moment:

  1. You can set "lib": ["dom"] in your tsconfig.json
  2. You can add /// <reference lib="dom" /> at the top of the files in which you use fetch

I personally prefer #2 as I can more easily keep track of where I am using this hack.

zVictor
  • 3,610
  • 3
  • 41
  • 56
  • 2
    This is a wrong answer! As others pointed out, this tells TypeScript that you intend to run this code in a browser environment, allowing you to use DOM-specific globals. This makes type checking more lax and can lead to unexpected runtime errors. – jlblca9l_kpblca Jun 15 '23 at 16:42
0

This GitHub issue "node@18.x.x version not fetch global api ?" for "@types/node" is still open, to quote the latest comment from one of maintainers,

The short version is that no one has implemented the types for fetch in this package yet. There are some ideas about how best to handle it but I don't know if there is actually a consensus among maintainers of this package. If you'd like to help with that, DT has good guidelines for getting started as a contributor, and I'm sure several people on this thread would be eager to review a MR.

There are proposed workarounds but I think maybe the easiest way is just to use // @ts-ignore above the fetch clause as we know for sure it is correct so we don't need ts check here.

Qiulang
  • 10,295
  • 11
  • 80
  • 129