将Fetch返回的WebStream转为Node Stream时TypeScript类型报错排查
问题:Fetch API返回的WebStream转Node Stream时TypeScript类型错误
我使用Node.js v18.7.0,尝试将原生Fetch API返回的WebStream转换为Node Stream,使用了node:stream模块的Readable.fromWeb方法。代码实际运行正常,但TypeScript抛出类型检查错误,添加@ts-ignore注释后可正常执行。
环境配置
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 } }
类型错误信息
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)
源代码
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 {}
请问这是Fetch类型定义存在Bug,还是我的操作存在问题?
解答
这是TypeScript类型定义的兼容性问题,不是你的操作错误。
原因是:
- Node.js的
Readable.fromWeb方法在类型定义中,期望接收的是Node自身实现的ReadableStream(来自node:stream/web模块),这个类型额外定义了values()方法和[Symbol.asyncIterator]符号; - 而Fetch API返回的是标准Web API的
ReadableStream类型(来自DOM类型定义),两者在类型层面不兼容,但实际运行时,Node 18内置的Fetch基于undici实现,其返回的Stream完全支持被Readable.fromWeb转换。
解决办法
- 类型断言:直接将Fetch返回的Stream断言为Node的Web Stream类型,替代
@ts-ignore:
const nodeStream = Readable.fromWeb(fetchRequest.body as unknown as import('node:stream/web').ReadableStream)
更新依赖:升级
@types/node到v18.11.0及以上版本,后续版本的类型定义已经修复了这个兼容性问题,会自动识别Fetch返回的Stream可以适配Readable.fromWeb的参数类型。临时方案:保留
@ts-ignore注释,但这只是规避检查的权宜之计,不推荐长期使用。
内容的提问来源于stack exchange,提问作者Dawei67
相关产品推荐
相关产品推荐

