Search code examples
node.jsfiledirectoryfilesystemsreaddir

Nodejs 14.5 Filesystem API what is the Dirent "Symbol(type)" property?


I am doing some basic readdir operations and file/directory read operations with Node 14.5 and filesystem api...

I am just wondering, as I get an "Dirent" object that describes a file/directory, when I iterate through the properties of it , I can see a "[Symbol(type)]" property with a number value, thats probably the type of that file.. however I cannot access that property in any way...

Dirent {
  name: 'Some name of file.mp4',
  [Symbol(type)]: 1
}

My question now is: what is that kind of property and how could I access it? Or how can I create such a property and why does is even show up? I know I can usee methods like isDirectory() etc. but I was just interested to know what that property is...

here is my code:

const fs = require('fs');
const path = require('path');

const walkDirs = async (dir_path, isSubdir = false, round = 0) => {
  try {
    const files = await fs.promises.readdir(dir_path);
    const dirs = fs.opendirSync(dir_path);
    // console.log(dirs);
    for await (const dirent of dirs) {
      for ( let prop in dirent) {
        console.log("prop:", prop,  dirent[prop]);
      }
    }

  } catch(error) {
    console.log("Error catched: ", error);
  }
}

walkDirs("D:/", false, 0);

Solution

  • If you go to the fs module's source code for the DirEnt class, you find this:

    class Dirent {
      constructor(name, type) {
        this.name = name;
        this[kType] = type;
      }
    
      isDirectory() {
        return this[kType] === UV_DIRENT_DIR;
      }
    
      isFile() {
        return this[kType] === UV_DIRENT_FILE;
      }
    
      isBlockDevice() {
        return this[kType] === UV_DIRENT_BLOCK;
      }
    
      isCharacterDevice() {
        return this[kType] === UV_DIRENT_CHAR;
      }
    
      isSymbolicLink() {
        return this[kType] === UV_DIRENT_LINK;
      }
    
      isFIFO() {
        return this[kType] === UV_DIRENT_FIFO;
      }
    
      isSocket() {
        return this[kType] === UV_DIRENT_SOCKET;
      }
    }
    

    If you then look for kType, you find this:

    const kType = Symbol('type');
    

    And, all the values in that code such as UV_DIRECT_DIR and UV_DIRENT_FILE are constants imported from libuv that describe the type of directory entry.

    So, it appears that the property you are asking about contains the libuv type for the directory entry and they are using a Symbol as the property name because they do not intend for that internal implementation detail to be used publicly or documented.

    If you don't know what libuv is, it's the cross platform library that nodejs uses to access OS services. It abstracts some operating system details into a common interface to allow more nodejs code to be written once and work on multiple platforms (Win/Mac/Unix).


    The underlying UV constants mentioned above are defined here in C++ code in libuv in uv.h.

    typedef enum {
      UV_DIRENT_UNKNOWN,
      UV_DIRENT_FILE,
      UV_DIRENT_DIR,
      UV_DIRENT_LINK,
      UV_DIRENT_FIFO,
      UV_DIRENT_SOCKET,
      UV_DIRENT_CHAR,
      UV_DIRENT_BLOCK
    } uv_dirent_type_t;