typescriptのfilterのコールバック関数で非同期処理を行いたいときに、少しハマったのでメモ。
下の例では、src/
にあるディレクトリのうち、空でないものを取り出している。
つまり、src/
の子の位置にあるディレクトリのうちaaa/
とccc/
を取り出している。
主なディレクトリ構成(簡単のためpackage.jsonなどは除く)
. ├──main.ts └── src ├── aaa │ └── README.md ├── bbb └── ccc └── README.md
ソースコード
import fs from 'node:fs/promises'; import path from 'node:path'; import fg from 'fast-glob'; // run with `yarn ts-node main.ts` void main(); async function main() { const sourceDirents = await fs.readdir(path.join('src'), { encoding: 'utf8', withFileTypes: true }); console.log('sourceDirents', sourceDirents); // NG // const filteredSourceDirents = sourceDirents.filter(async (d) => { // if (!d.isDirectory()) return false; // const dir = await fg(path.join('src', d.name, '*')); // return dir.length > 0; // }); // OK const filteredSourceDirents = await Promise.all( sourceDirents.map(async (d) => { if (!d.isDirectory()) return false; const dir = await fg(path.join('src', d.name, '*')); return dir.length > 0; }) ).then((res) => sourceDirents.filter((_, i) => res[i])); console.log('filteredSourceDirents', filteredSourceDirents); }
実行結果
sourceDirents [ Dirent { name: 'aaa', [Symbol(type)]: 2 }, Dirent { name: 'bbb', [Symbol(type)]: 2 }, Dirent { name: 'ccc', [Symbol(type)]: 2 } ] filteredSourceDirents [ Dirent { name: 'aaa', [Symbol(type)]: 2 }, Dirent { name: 'ccc', [Symbol(type)]: 2 } ]
実行結果から、aaa
とccc
のディレクトリを取り出すことができているのが確認できる。