TypeScript 初心者ですがちょっとハマったので fetch したものを async iterate (async wait) する方法を書いておきます。
まず、具体的な問題はReadableStream<string>
オブジェクトを async wait
で async iterate しようとすると "Type 'ReadableStream' is not an array type or a string type." というエラーが出てしまう、というものです。
なお環境は ts-node v10.9.2 (Ubuntu 24.04の標準) で fetch を使うために以下の設定をしています。
{
"compilerOptions": {
"lib": ["ESNext", "DOM"]
}
}
どうも原因は ReadableStream<string>
が async wait
に必要な [Symbol.asyncIterator]
を実装しているのに TypeScript 側で AsyncIterable<string>
を継承していないことにあるようで、必要だったのは as unknown as AsyncIterable<string>
でした。
export async function fetchStream(url: string, method:string = 'GET'): Promise<AsyncIterable<string>> {
const res = await fetch(url, { method: method } )
if(res.status !== 200 || !res.body) return null
return (res.body.pipeThrough(new TextDecoderStream()) as unknown as AsyncIterable<string>)
}
export async function main() {
const stream = await fetchStream('https://triple-underscore.github.io/rfc-others/RFC2616-ja.html')
if(!stream) return;
for await (const chunk of stream) {
console.log("chunk: " + chunk)
}
}
main();
追記
コメントで教えてもらいましたが、この問題は既に新しい TypeScript で修正されているようです(Node.js v23.10.0 で確認)。
また ts-node は開発停止していて、本家の Node.js が直接 TypeScript に対応したようです。
export async function fetchStream(url: string, method:string = 'GET'): Promise<ReadStream<string>> {
const res = await fetch(url, { method: method } )
if(res.status !== 200 || !res.body) return null
return res.body.pipeThrough(new TextDecoderStream())
}
export async function main() {
const stream = await fetchStream('https://triple-underscore.github.io/rfc-others/RFC2616-ja.html')
if(!stream) return;
for await (const chunk of stream) {
console.log("chunk: " + chunk)
}
}
main();
$ node fetch.ts | grep chunk
(node:600168) ExperimentalWarning: Type Stripping is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:600168) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/vipper36/Desktop/ide/fetch_test/fetch.ts is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /home/vipper36/Desktop/ide/fetch_test/package.json.
chunk: (以下略)