TypeScript + Node.js
Node itself ships no types — @types/node (Module 09) supplies them, and without it process, Buffer and the rest of the standard library are compile errors even though the code runs fine. process.argv is always string[]: command-line arguments have no other type, whatever they look like.
Typing process.argv and a callback-based fs read
Two Node habits worth typing correctly from day one: destructuring argv with a typed fallback, and a Node-style error-first callback, where the error parameter is always NodeJS.ErrnoException | null — never a bare Error, because null is how Node signals success.
// npm i -D @types/node
import { readFile } from "node:fs"
// argv is ALWAYS string[] — argv[0] is the node binary, argv[1] the script
const [, , command, ...rest] = process.argv
const target: string = rest[0] ?? "."
function loadConfig(
path: string,
cb: (err: NodeJS.ErrnoException | null, data?: string) => void,
): void {
readFile(path, "utf8", (err, data) => {
if (err) return cb(err)
cb(null, data)
})
}
loadConfig(`${target}/config.json`, (err, data) => {
if (err) {
console.error("failed to read config:", err.message)
process.exitCode = 1
return
}
console.log("config:", data)
})process.argv — every element is a plain string, whether it looks like a number, a flag, or a path. Parsing (Number(rest[0]), a real flag parser) is always your responsibility, not something a type can do for you.JuniorWhy is the error parameter in a Node-style callback typed NodeJS.ErrnoException | null instead of just Error?
Node's callback convention signals success by passing null as the error argument, not by omitting it — so the parameter has to include null in its type or every successful call would be a type error. NodeJS.ErrnoException extends Error with the extra fields Node's own APIs actually set, like code and errno, which a plain Error type would not expose without a cast.
