21

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:

7
  • 1
    Given that it's experimental it's presumably not yet in @types/node. Commented Feb 28, 2022 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? Commented Feb 28, 2022 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. stackoverflow.com/a/43523944/3001761. Commented Feb 28, 2022 at 11:28
  • 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. Commented Apr 20, 2022 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? Commented Sep 16, 2022 at 16:04

5 Answers 5

19

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

Sign up to request clarification or add additional context in comments.

4 Comments

thanks! do you know when we can expect this to be part of typescript OOTB?
You're welcome. Sadly not. People expecting it to be added, as soon as node does not consider this feature experimental anymore.
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.
Another note, I did not have to install the undici package, as node has it included already in my current version v18.15.0
14

There are only 2 easy/lazy solutions at the moment (check Ruben's answer for a proper one):

  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.

Beware that "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".

2 Comments

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.
Thanks for the correction. I have updated the answer accordingly.
4

This GitHub issue "[email protected] 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.

Comments

3

Similar to what @zVictor said, but I recommend to wrap the hack in it's own file.

Create a file "fetch.ts" in your project, with this content:

/// <reference lib="dom" />

type _Response = Response;
const _fetch = fetch;

export type { _Response as Response };
export { _fetch as fetch };

Then you can import fetch from the rest of your project and you don't need to clutter your codebase with /// <reference lib="dom" /> statements.

Comments

3

Long story short, post-2023, Node.js v18+, the least-hassle answer is to just install and import undici, all types are in place there now:

npm install --save undici
import { fetch } from "undici";

(source)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.