API reference

File system (fs)

19/21Coverage13/21Strict (zero caveats)

Node's fs, ported from lib/fs.js to TypeScript: the synchronous functions, their callback and promise forms, FileHandle, the file streams and fs.watch. Each operation is one native request — on the calling thread for a *Sync function, on the thread pool with the callback on the event loop otherwise — as libuv's are.

Exact Works, with caveats Not supported

fs.readFileSync(path[, options])

Exact
readFileSync(path: PathOrFileDescriptor, options?: BufferEncoding | { encoding?, flag? }): string | Buffer

Reads the whole file: a Buffer of its exact bytes with no encoding, a string decoded in any Buffer encoding with one. A file descriptor reads to its end (readFileSync(0, 'utf8') is stdin). Errors are Node's system errors, with code, errno, syscall and path. Node's lib/fs.js, ported to TypeScript over one native request per operation.

Returns

string | Buffer — The contents.

const text = fs.readFileSync('config.json', 'utf8')
See it in a full example →

fs.writeFileSync / fs.appendFileSync

Exact
writeFileSync(file: PathOrFileDescriptor, data: string | ArrayBufferView, options?: WriteFileOptions): void

Writes (or appends) a string in any encoding or any ArrayBufferView to a path or descriptor, with Node's { encoding, mode, flag, flush } options.

fs.writeFileSync('/tmp/out.txt', 'hello\n')
fs.appendFileSync('/tmp/out.txt', 'more')
See it in a full example →

fs.existsSync / fs.accessSync

Exact
existsSync(path: PathLike): boolean; accessSync(path: PathLike, mode?: number): void

existsSync reports whether the path exists and never throws; accessSync throws Node's error when the process lacks the access mode (F_OK, R_OK, W_OK, X_OK).

console.log(fs.existsSync('/tmp/out.txt'))
See it in a full example →

fs.statSync / lstatSync / fstatSync

Works, with caveats
statSync(path: PathLike, options?: { throwIfNoEntry? }): Stats

Node's Stats: the numeric fields (dev, mode, nlink, uid, gid, rdev, blksize, ino, size, blocks, atimeMs, mtimeMs, ctimeMs, birthtimeMs), the atime/mtime/ctime/birthtime Dates and the kind predicates. throwIfNoEntry: false returns undefined for a missing path. On Linux the stat is statx, so birthtime is real.

const st = fs.statSync('/tmp/out.txt')
console.log(st.size, st.isFile(), st.mtime)
⚠ Differences from standard
  • { bigint: true } is ignored: no BigIntStats.

fs.statfsSync(path) → StatFs

Works, with caveats
statfsSync(path: PathLike): StatFs

File-system statistics of the volume holding path: { type, bsize, frsize, blocks, bfree, bavail, files, ffree }.

console.log(fs.statfsSync('/').bavail)
⚠ Differences from standard
  • { bigint: true } is ignored: the fields are numbers.

fs.mkdirSync / mkdtempSync / rmdirSync / rmSync / unlinkSync

Works, with caveats
mkdirSync(path, options?: Mode | { recursive?, mode? }): string | undefined; rmSync(path, options?: { recursive?, force? }): void

Directory creation (recursive returns the first directory made), temporary directories, and removal: rmSync removes a tree with recursive and ignores a missing path with force; a directory without recursive is Node's ERR_FS_EISDIR.

fs.mkdirSync('/tmp/a/b/c', { recursive: true })
fs.rmSync('/tmp/a', { recursive: true, force: true })
See it in a full example →
⚠ Differences from standard
  • rmSync's maxRetries/retryDelay are validated and unused.

fs.readdirSync(path[, options])

Works, with caveats
readdirSync(path, options?: { encoding?, withFileTypes?, recursive? }): string[] | Buffer[] | Dirent[]

A directory's entries, sorted as libuv sorts them: names, Buffers with encoding: 'buffer', or Dirents (name, parentPath, the kind predicates) with withFileTypes; recursive walks the subtree breadth-first.

for (const d of fs.readdirSync('.', { withFileTypes: true })) console.log(d.name, d.isDirectory())
See it in a full example →
⚠ Differences from standard
  • dirent.path (removed in Node v24) is a compile-time error rather than undefined.

fs.renameSync / copyFileSync / linkSync / symlinkSync / readlinkSync / realpathSync

Works, with caveats
renameSync(oldPath, newPath): void; copyFileSync(src, dest, mode?): void; realpathSync(path): string

Moving, copying (the copy takes the source's mode; COPYFILE_EXCL refuses an existing destination), hard and symbolic links, and path canonicalization: realpathSync is Node's lstat walk, realpathSync.native is realpath(3). Two-path errors name both paths.

fs.copyFileSync('a.txt', 'b.txt', fs.constants.COPYFILE_EXCL)
See it in a full example →
⚠ Differences from standard
  • COPYFILE_FICLONE_FORCE fails with ENOTSUP: no copy-on-write clone.

fs.openSync / closeSync / readSync / writeSync / readvSync / writevSync

Exact
openSync(path, flags?, mode?): number; readSync(fd, buffer, offset?, length?, position?): number; writeSync(fd, data, …): number

The descriptor-level API: open with any flag string or a numeric mask, read and write buffers (offset, length, position, or an options object) or strings (position, encoding), scatter/gather, close.

const fd = fs.openSync('/tmp/out.txt', 'r')
const n = fs.readSync(fd, Buffer.alloc(16), 0, 16, 0)
fs.closeSync(fd)

fs.fsyncSync / fdatasyncSync / ftruncateSync / truncateSync

Exact
fsyncSync(fd): void; ftruncateSync(fd, len?): void; truncateSync(path, len?): void

Flush a descriptor to disk and resize a file, by descriptor or path.

fs.truncateSync('/tmp/out.txt', 0)

fs.chmodSync / fchmodSync / chownSync / fchownSync / lchownSync

Exact
chmodSync(path, mode: number | string): void; chownSync(path, uid, gid): void

Permission bits (a number or an octal string) and ownership, by path or descriptor. The chown family does nothing on Windows, as libuv's.

fs.chmodSync('/tmp/out.txt', 0o600)

fs.utimesSync / futimesSync / lutimesSync

Exact
utimesSync(path, atime: number | string | Date, mtime: number | string | Date): void

Set access and modification times, as seconds, a numeric string or a Date, by path, descriptor or link.

fs.utimesSync('/tmp/out.txt', new Date(), new Date())

Callback forms

Exact
fs.readFile(path[, options], cb); fs.stat(path, cb); fs.mkdir(path[, options], cb); …

Every operation's callback form: each request runs on the thread pool and calls back on the event loop, as libuv's do. readFile and writeFile take an AbortSignal.

fs.readFile('config.json', 'utf8', (err, text) => { if (err) throw err; console.log(text) })
See it in a full example →

fs.promises / fs/promises

Exact
import { readFile, writeFile, stat, readdir, … } from 'fs/promises'

Node's promise API: each function is its callback form's request settling a promise; readFile/writeFile/appendFile also take a FileHandle.

const text = await fs.promises.readFile('config.json', 'utf8')
See it in a full example →

fs.open / read / write / writev / readv / fsync / close

Exact
fs.open(path, flags?, mode?, cb); fs.read(fd, buffer, offset, length, position, cb); fs.write(fd, data, …, cb)

The descriptor-level callback operations with Node's argument forms, validation errors and system errors. A positioned read or write is a single transfer at the offset on every platform.

fs.open('a.txt', 'r', (err, fd) => fs.close(fd))

fsPromises.open → FileHandle

Works, with caveats
open(path, flags?, mode?): Promise<FileHandle>

Opens a file and resolves to a FileHandle: fd, read, write, writev, sync, datasync, stat, truncate, chmod, utimes, readFile, writeFile, appendFile, createReadStream/createWriteStream, and close, which waits for the streams that hold the handle.

import { open } from 'fs/promises'
const h = await open('a.txt')
await h.close()
⚠ Differences from standard
  • Not ported: chown, readv, readLines, readableWebStream, [Symbol.asyncDispose].

fs.createReadStream / createWriteStream

Exact
fs.createReadStream(path, options?): fs.ReadStream; fs.createWriteStream(path, options?): fs.WriteStream

Readable and Writable streams over a file, with Node's options (start/end, flags, mode, fd, fs, signal, autoClose, emitClose, flush, highWaterMark). Node's lib/internal/fs/streams.js.

fs.createReadStream('in.txt').pipe(fs.createWriteStream('out.txt'))
See it in a full example →

fs.watch

Exact
fs.watch(filename, options?, listener?): FSWatcher

Native, event-driven change watching in the event loop: an FSWatcher (an EventEmitter) emitting 'change' with (eventType, filename), and 'close', with ref()/unref() and persistent. libuv on every platform; recursive watches the whole tree, with names relative to the watched directory.

const w = fs.watch('config.json', (ev, name) => { console.log(ev, name); w.close() })
See it in a full example →

fs.constants

Exact
fs.constants: { O_*, S_*, F_OK, R_OK, W_OK, X_OK, COPYFILE_*, UV_* }

Node's per-platform constants table, a real object.

fs.accessSync('a.txt', fs.constants.R_OK)

fs.cp / opendir / glob / watchFile / openAsBlob / lchmod

Not supported
// not supported yet

Not ported yet.

// not supported yet

File / FileReader / FileSystemFileHandle

Not supported
// not supported

The browser-flavored File API is not planned — these model browser sandbox/permission concepts this compiler has no equivalent for. A native CLI/microservice program has direct filesystem access via the fs functions above instead.