clone-stats review
clone-stats copies the enumerable fields of a Node `fs.Stats` object into a newly constructed `fs.Stats`, so methods such as `isFile()` remain available on the copy. That narrow job is the whole package. Version 1.0.0 is still the current release, with no runtime dependencies and no newer API since its 2016 publication. Our Node 22 check found that ordinary CommonJS and ESM loading work, but the implementation uses the deprecated public `fs.Stats` constructor and is unsuitable for BigInt stat results.
clone-stats 1.0.0 took 0.7 seconds and 1 MB in our install, but its only function triggers a deprecated Node constructor path and cannot safely clone BigInt stats. Keep it inside legacy dependency chains; new filesystem code should store an explicit metadata record instead.
We installed it
| Install | ✓ · 0.7s | 1 package on disk · 1 MB |
| Import | ✓ | ESM import works · require() works · CommonJS package |
| Browser | n/a | could not be bundled for the browser (Node-only code, most likely) |
| Types | — | no TypeScript types found |
| Known vulns | 0 | 0 critical · 0 high · 0 moderate · 0 low (npm audit) |
Answers from our run
Does clone-stats install cleanly?
Yes. In a fresh container with an empty cache, npm install clone-stats finished in 0.7s, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.
Can clone-stats run in a browser?
Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.
Does clone-stats work with both ESM and CommonJS?
Yes. Both import 'clone-stats' and require('clone-stats') worked in Node 22 in our run. The package is published as CommonJS.
Does clone-stats include TypeScript types?
No type declarations were found in our install, so TypeScript users need their own declarations.
clone-stats or clone: which should you use?
clone: Choose it for general object graphs when circular references and prototype handling matter. clone-stats 1.0.0 took 0.7 seconds and 1 MB in our install, but its only function triggers a deprecated Node constructor path and cannot safely clone BigInt stats.
When should you not use clone-stats?
You are writing new Node code. The sole function calls new fs.Stats(), which Node 22 reports through the DEP0180 deprecation warning.
Use it if
- An older Node build tool already expects clone-stats and passes ordinary number-based `fs.Stats` objects.
- You need a writable copy that retains `isFile()`, `isDirectory()`, and the other Stats prototype checks.
- Compatibility with a legacy vinyl-style pipeline matters more than support for newer filesystem object variants.
- You are writing new Node code. The sole function calls `new fs.Stats()`, which Node 22 reports through the DEP0180 deprecation warning.
- Your stat calls use `{ bigint: true }`. A BigIntStats source is copied onto a number-mode Stats instance, and predicate methods can then throw over mixed numeric types.
- You need a faithful object clone. Only enumerable top-level properties are assigned, so descriptors, symbols, subclass identity, and nested-object independence are absent.
- Your TypeScript project cannot carry a local declaration. The 24 KB package includes no type definitions.
- You want a maintained compatibility promise. The README calls the project experimental, npm still serves 1.0.0 from 2016, and the repository has not published a fix for the constructor deprecation.
Setup reality
Our fresh Node 22 Bookworm install of clone-stats 1.0.0 completed in 0.7 seconds. It left 1 package and 1 MB on disk, with 24 KB unpacked. The package declares 0 direct dependencies and 0 peer dependencies, and npm audit found 0 known vulnerabilities across every severity level. There are no native builds, credentials, environment variables, or configuration files to prepare.
The package is CommonJS and has no exports map. Both require('clone-stats') and ESM import worked in our sandbox, but no TypeScript declarations were present. Put a small declare module file beside legacy typed code if removal is not yet practical. Our browser build failed in esbuild because the implementation depends on Node filesystem internals, so keep it out of client bundles.
The first call can produce Node's DEP0180 warning because version 1.0.0 constructs fs.Stats directly. It then iterates Object.keys(source) and assigns those values to the new object. That means the operation is shallow and does not preserve non-enumerable fields, symbol fields, property descriptors, or a custom subclass prototype. It also performs no input check before reading the source keys.
Do not pass the result of fs.stat(..., { bigint: true }). That object uses BigInt fields and different predicate arithmetic; transplanting its fields onto an ordinary Stats instance can make isFile() and related calls fail with a mixed-number-type error. For caches, workers, or serialization, copy the exact fields your application owns into a plain record instead.
Patterns
Copy a synchronous stat result clone-sync-stat
const fs = require('node:fs')
const cloneStats = require('clone-stats')
const source = fs.statSync('report.pdf')
const copy = cloneStats(source)
console.log(copy.size, copy.isFile())Use number-based stats only. On Node 22, the clone call can emit DEP0180 because version 1.0.0 constructs `fs.Stats` directly.
Copy metadata from callback fs.stat clone-callback-stat
fs.stat('uploads/photo.jpg', (error, stats) => {
if (error) throw error
const copy = cloneStats(stats)
console.log(copy.mtime)
})The package performs its copy synchronously after `fs.stat` returns; it does not add I/O or alter filesystem errors.
Use it from an ESM module clone-promise-stat
import { stat } from 'node:fs/promises'
import cloneStats from 'clone-stats'
const source = await stat('package.json')
const copy = cloneStats(source)
console.log(copy.isFile())Our ESM import worked through Node's CommonJS interop. The package has neither a native ESM build nor an exports map.
Retain the Stats predicate methods retain-stat-methods
const spread = { ...source }
const copy = cloneStats(source)
console.log(typeof spread.isDirectory)
console.log(copy.isDirectory())Object spread produces a plain object, while clone-stats creates an `fs.Stats` instance whose prototype supplies the predicates.
Replace fields on the copied object change-copy-fields
const source = fs.statSync('asset.css')
const copy = cloneStats(source)
copy.size = 0
copy.mtime = new Date(0)
console.log(source.size, copy.size)Top-level reassignment leaves the source field alone. The copy is shallow, so mutating a shared object value in place is a different case.
Keep symlink predicates from lstat copy-lstat-result
const source = fs.lstatSync('current')
const copy = cloneStats(source)
if (copy.isSymbolicLink()) console.log('symlink')Call `lstat` when the link is the subject. `stat` follows the link before clone-stats receives anything.
Check the input before cloning reject-wrong-input
function checkedClone(value) {
if (!(value instanceof fs.Stats)) {
throw new TypeError('Expected fs.Stats')
}
return cloneStats(value)
}Version 1.0.0 has no input guard. `null` throws during key enumeration, while a plain object can create an incomplete Stats value.
Store selected BigInt fields instead avoid-bigint-stats
const precise = fs.statSync('archive.tar', { bigint: true })
const snapshot = {
size: precise.size,
mtimeNs: precise.mtimeNs,
isFile: precise.isFile(),
}Do not feed BigIntStats to clone-stats. Its ordinary Stats target can fail when predicates combine copied BigInt fields with number constants.
Add a narrow local declaration declare-types-locally
declare module 'clone-stats' {
import type { Stats } from 'node:fs'
function cloneStats(stats: Stats): Stats
export = cloneStats
}The npm package contains no TypeScript types. Keeping the declaration limited to `Stats` avoids promising unsupported BigIntStats behavior.
Create an application-owned snapshot make-serializable-snapshot
const stats = await fs.promises.stat('video.mp4')
const snapshot = {
size: stats.size,
mode: stats.mode,
modifiedAt: stats.mtime.toISOString(),
kind: stats.isFile() ? 'file' : 'other',
}An explicit plain record is safer for JSON, caches, and worker messages because it does not depend on the runtime's Stats constructor.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| clone | npm | Choose it for general object graphs when circular references and prototype handling matter. |
| lodash.clonedeep | npm | Choose it for familiar deep-copy behavior on application data, after testing special Node objects. |
| rfdc | npm | Choose it for fast cloning of ordinary data structures rather than `fs.Stats` compatibility. |
More utils guides
lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

