0

I have a function that recursively searches a directory for files and returns them as an array. I only want files that end with ".js" or ".ts". For that, I'm trying to use Array.filter(). However, it looks as if this would not work, since only files ending in ".js" are returned. How can I filter only the files ending in ".js" or ".ts"?

function getFiles(dir: string): string[] {
    let files: string[] = [];
    fs.readdirSync(dir).forEach((file) => {
        if (fs.statSync(path.join(dir, file)).isDirectory()) {
            files = files.concat(getFiles(path.join(dir, file)));
        } else {
            files.push(path.join(dir, file));
        }
    });
    return files;
}

const files = getFiles(path.join(__dirname, "xyz")).filter((file) => file.endsWith(".js" || ".ts"));
  • 1
    `file => file.endsWith(".js" || ".ts")` doesn't do what you probably think it does. What you are looking for is `file => file.endsWith(".js") || file.endsWith(".ts")`. Function calls do not distribute over logical or operator `||`, rather, the expression `".js" || ".ts"` ultimately ends up as just `".js"` since that string is a truthy value. – CRice Apr 12 '22 at 22:00
  • Ohh... I thought it would work like that. Thanks for the quick help! –  Apr 12 '22 at 22:08

2 Answers2

0

Why don't use just use an existing package, like rrdir?

That takes care of matching (and excluding). It also deals with errors, and whether or not symlinks should be followed.

Then it's as easy as

const rrdir = require("rrdir");
const opts  = { include: [ '**/*.{js,ts}' ] };

for await ( const entry of rrdir( 'path/to/root' , opts ) ) {
  // => { path: 'path/to/root/. . ./file', directory: false, symlink: false }
}

Or if you're willing to wait for the entire tree be be collected before getting anything back:

const rrdir = require('rrdir');
const opts  = { include: [ '**/*.{js,ts}' ] };
const files = rrdir.sync( 'path/to/root', opts ) ;
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
0

".js" || ".ts" evaluates to .js. Unfortunately you can't pass a condition like this. Try running ".js" || ".ts" in a browser console to see.

This would be the correct version:

const files = getFiles(path.join(__dirname, "xyz"))
  .filter(file => file.endsWith(".js") || file.endsWith(".ts"));

Alternatively:

const files = getFiles(path.join(__dirname, "xyz"))
  .filter(file => file.match(/(j|t)s$/);
Evert
  • 93,428
  • 18
  • 118
  • 189