Reading Files in TypeScript

Here’s the translation of the Go code example for reading files into TypeScript, along with explanations in Markdown format suitable for Hugo:

Reading and writing files are basic tasks needed for many TypeScript programs. First we’ll look at some examples of reading files.

import * as fs from 'fs';

// Reading files requires checking most calls for errors.
// This helper will streamline our error checks below.
function check(e: Error | null) {
    if (e !== null) {
        throw e;
    }
}

// Perhaps the most basic file reading task is
// slurping a file's entire contents into memory.
const dat = fs.readFileSync('/tmp/dat', 'utf8');
console.log(dat);

// You'll often want more control over how and what
// parts of a file are read. For these tasks, start
// by opening a file to obtain a file descriptor.
const fd = fs.openSync('/tmp/dat', 'r');

// Read some bytes from the beginning of the file.
// Allow up to 5 to be read but also note how many
// actually were read.
const b1 = Buffer.alloc(5);
const n1 = fs.readSync(fd, b1, 0, 5, null);
console.log(`${n1} bytes: ${b1.toString('utf8', 0, n1)}`);

// You can also seek to a known location in the file
// and read from there.
fs.readSync(fd, b1, 0, 2, 6);
console.log(`2 bytes @ 6: ${b1.toString('utf8', 0, 2)}`);

// The fs package provides some functions that may
// be helpful for file reading. For example, reads
// like the ones above can be more robustly
// implemented with readSync.
const b3 = Buffer.alloc(2);
fs.readSync(fd, b3, 0, 2, 6);
console.log(`2 bytes @ 6: ${b3.toString('utf8')}`);

// There is no built-in rewind, but
// seeking to the start accomplishes this.
fs.readSync(fd, b1, 0, 5, 0);
console.log(`5 bytes: ${b1.toString('utf8', 0, 5)}`);

// Close the file when you're done (usually this would
// be scheduled immediately after opening with
// try...finally or using 'with' statement in TypeScript).
fs.closeSync(fd);

To run this program:

$ echo "hello" > /tmp/dat
$ echo "typescript" >> /tmp/dat
$ ts-node reading-files.ts
hello
typescript
5 bytes: hello
2 bytes @ 6: ty
2 bytes @ 6: ty
5 bytes: hello

In this TypeScript version:

  1. We use the built-in fs module for file operations.
  2. Instead of os.ReadFile, we use fs.readFileSync.
  3. We use fs.openSync to open the file and get a file descriptor.
  4. fs.readSync is used for reading specific portions of the file.
  5. We use Buffer instead of byte slices for reading binary data.
  6. There’s no direct equivalent to io.ReadAtLeast or bufio.NewReader, so we stick with fs.readSync.
  7. Error handling is done through exceptions rather than returned errors.

Note that this example uses synchronous file operations for simplicity. In a real-world Node.js application, you’d typically use asynchronous versions of these functions to avoid blocking the event loop.

Next, we’ll look at writing files.