node.jsfses6-modules

Why doesn't 'fs' work when imported as an ES6 module?


Why do I get errors like these when I try to use the new Node.js support for ES6 modules (e.g. with node --experimental-modules script.mjs)?

// script.mjs
import * as fs from 'fs';

// TypeError: fs.readFile is not a function
fs.readFile('data.csv', 'utf8', (err, data) => {
    if (!err) {
        console.log(data);
    }
});
// TypeError: fs.readdirSync is not a function
fs.readdirSync('.').forEach(fileName => {
    console.log(fileName);
});

Solution

  • You must use import fs from 'fs', not import * as fs from 'fs'.

    This is because (at least from the point of view of mjs files) the 'fs' module exports only one thing, which is called default. So if you write import * as fs from 'fs', fs.default.readFile exists but fs.readFile does not. Perhaps the same is true of all Node.js (CommonJS) modules.

    Confusingly, in TypeScript modules (with @types/node and ES5 output), import fs from 'fs' produces error

    error TS1192: Module '"fs"' has no default export
    

    so in TypeScript you must write import * as fs from 'fs'; by default. It appears this can be changed to match the way mjs files work using the new "esModuleInterop": true option in tsconfig.json.