Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript error converting a native fetch body webstream to a node stream

package.json

{
  "type": "module",
  "dependencies": {
    "@types/node": "^18.6.5",
    "typescript": "^4.7.4"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2021",
    "module": "ESNext",
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

Using node v18.7.0, I am trying to convert a webstream returned from the native fetch API to a node stream. I use Readable.fromWeb method from 'node:stream' module. Typescript is returning a typecheck error but code is working as expected with a @ts-ignore comment.

Type error

 Argument of type 'ReadableStream<Uint8Array>' is not assignable to parameter of type 'ReadableStream<any>'.
  Type 'ReadableStream<Uint8Array>' is missing the following properties from type 'ReadableStream<any>': values, [Symbol.asyncIterator]

const nodeStream = Readable.fromWeb(fetchRequest.body)

Source code

import { Readable } from 'node:stream'
import { pipeline } from 'stream/promises'
import fs from 'fs'

const fetchRequest = await fetch('https://www.npmjs.com/')

if (fetchRequest.body) {
  // Argument of type 'ReadableStream<Uint8Array>' is not assignable to parameter of type 'ReadableStream<any>'.
  // Type 'ReadableStream<Uint8Array>' is missing the following properties from type 'ReadableStream<any>': values, [Symbol.asyncIterator]
  // @ts-ignore
  const nodeStream = Readable.fromWeb(fetchRequest.body)

  await pipeline(nodeStream, fs.createWriteStream('output.html'))
}

export {}

Is there a bug with fetch typings or I am doing something wrong ?

Here is a reproduction playground

like image 845
Dawei67 Avatar asked Feb 28 '26 00:02

Dawei67


1 Answers

The problem is that your fetch is not the nodejs fetch, it's DOM fetch
@types/NodeJS doesn't have fetch
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/60924#issuecomment-1236920407

ThisIsNotTheFetchYouAreLookingFor.jpg


You may fix this with

import type * as streamWeb from 'node:stream/web';
declare global {
  interface Response {
    readonly body: streamWeb.ReadableStream<Uint8Array> | null;
  }
}

as streamWeb.ReadableStream extends ReadableStream

, or using external definitions like in the linked thread

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

export {}
like image 115
Dimava Avatar answered Mar 02 '26 15:03

Dimava



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!