Writing Files in TypeScript

Here’s the TypeScript translation of the Go code example for writing files:

Writing files in TypeScript follows similar patterns to the ones we saw earlier for reading.

import * as fs from 'fs';

function check(e: Error | null) {
    if (e !== null) {
        throw e;
    }
}

// To start, here's how to dump a string (or just bytes) into a file.
const d1 = Buffer.from("hello\nTypeScript\n");
fs.writeFile("/tmp/dat1", d1, { mode: 0o644 }, (err) => {
    check(err);
});

// For more granular writes, open a file for writing.
const f = fs.createWriteStream("/tmp/dat2");

// It's idiomatic to use a try-finally block to ensure the file is closed
try {
    // You can write byte arrays as you'd expect.
    const d2 = Buffer.from([115, 111, 109, 101, 10]);
    const n2 = f.write(d2);
    console.log(`wrote ${n2} bytes`);

    // A write method for strings is also available.
    const n3 = f.write("writes\n");
    console.log(`wrote ${n3} bytes`);

    // Use end() to finish writing and close the file
    f.end();

    // For buffered writes, you can use a BufferWriter
    const w = fs.createWriteStream("/tmp/dat3", { flags: 'a' });
    const n4 = w.write("buffered\n");
    console.log(`wrote ${n4} bytes`);

    // Use end() to ensure all buffered operations have been applied
    w.end();
} finally {
    f.close();
}

Try running the file-writing code:

$ ts-node writing-files.ts
wrote 5 bytes
wrote 7 bytes
wrote 9 bytes

Then check the contents of the written files:

$ cat /tmp/dat1
hello
TypeScript

$ cat /tmp/dat2
some
writes

$ cat /tmp/dat3
buffered

In this TypeScript version, we use the fs module to handle file operations. The writeFile function is used for simple file writing, while createWriteStream is used for more granular control.

Unlike Go, TypeScript (running on Node.js) uses an asynchronous model for file I/O. We’ve used the synchronous versions of these functions for simplicity, but in a real application, you’d typically use the asynchronous versions to avoid blocking the event loop.

The Buffer class is used to handle binary data, similar to byte slices in Go.

Instead of defer, we use a try-finally block to ensure the file is closed even if an error occurs.

The Sync operation doesn’t have a direct equivalent in Node.js as the OS handles file system syncing, but calling close() on a file stream ensures all data is written.

Next, we’ll look at applying some of the file I/O ideas we’ve just seen to the stdin and stdout streams.