21

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);
});

4 Answers 4

40

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.

Sign up to request clarification or add additional context in comments.

3 Comments

fs is a core module in node, you don't need to import it at all. It's always there.
Failure to import fs will cause ReferenceError: fs is not defined, even if it's not an .mjs module.
TypeScript is for type safety, so you should import your types. It's similar to using var fs = require('fs'); but we have to do some trickery for TS to get it just right. I was able to get it using Import * as fs from 'fs';, but not Import fs from 'fs';. I have been able to do the latter with most node modules when enabling the esModuleInterop and allowSyntheticDefaultImports, but not fs :( This one does work, for example: import path from 'path';
7

We can simply import like this it in our code

import * as fs from 'fs';

and it is perfectly working for me, give it a try

1 Comment

My question has those exact characters on the first line of code (in the same order too)
5

Adding "esModuleInterop": true in my tsconfig.json file fixed the issue

Comments

3

For recent ES versions (as ES2020 for example), the good way to do this is :

import { readFileSync, writeFileSync } from 'fs';

then in your code, simply use it

const cfg = readFileSync("./toto.json", "utf8");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.