JSON Configuration Files: package.json, tsconfig.json and JSONC

Intermediate
11 min

JSON Configuration Files: package.json, tsconfig.json and JSONC

Open any modern repository and the first files you meet are JSON: package.json, tsconfig.json, .prettierrc, settings.json, composer.json, appsettings.json. In this lesson you will learn how to read and edit the most important ones, why some of them allow comments even though JSON does not, how the $schema key gives you autocomplete, and when a different format such as YAML or TOML is the better tool.

Why Tools Chose JSON

JSON won the configuration space for practical reasons: every language parses it, its strict grammar leaves no ambiguity, tools can rewrite it without losing structure, and editors validate it as you type. Its two weaknesses, no comments and no trailing commas, are what the variants later in this lesson address.

Anatomy of package.json

package.json describes a Node.js project. The sample at the top shows the fields you will touch most:

| Field | Meaning | |-------|---------| | name, version | Package identity; version follows semantic versioning (major.minor.patch) | | private | true prevents accidental publishing | | type | "module" makes .js files ES modules; omit or "commonjs" for require | | main, exports | Entry point(s) other packages import | | scripts | Commands run with npm run <name>; npm test and npm start are shortcuts | | dependencies, devDependencies | Runtime vs development-only packages with version ranges | | engines | Node.js versions the project supports |

Version ranges use semver operators: ^5.1.0 accepts any 5.x.y at or above 5.1.0, ~5.1.0 accepts only 5.1.x, and a bare 5.1.0 pins exactly. Hand-editing is fine, but npm also edits the file for you and keeps it valid:

bash
npm pkg set scripts.build="tsc -p ." # add or change a nested key npm pkg get version # read a value npm pkg delete scripts.lint # remove a key npm install express@^5 # updates dependencies for you

Because package.json is parsed with a strict parser, a single comment or trailing comma breaks every npm command with JSON.parse errors. If you need a note, the community convention is a "//" key with a string value; npm ignores keys it does not know.

tsconfig.json and JSONC

The TypeScript compiler reads tsconfig.json with a lenient parser that accepts comments and trailing commas. This dialect is called JSONC (JSON with Comments) and is also used by VS Code's settings.json, launch.json, .devcontainer/devcontainer.json and Deno's config:

jsonc
{ // Shared settings live in a base file; this one only overrides "extends": "./tsconfig.base.json", "compilerOptions": { "target": "ES2022", "module": "NodeNext", "strict": true, "outDir": "dist", // trailing comma is tolerated by tsc }, "include": ["src"], }

The catch is that JSONC is not JSON: JSON.parse rejects it, and so do most standard libraries. When your own code must read such a file, use a dedicated parser such as the jsonc-parser package or strip comments first.

The $schema Key: Autocomplete for Config Files

Most config formats publish a JSON Schema describing their allowed keys. Point a file at its schema with a top-level $schema property and your editor validates keys and values and offers completions:

json
{ "$schema": "https://json.schemastore.org/prettierrc", "semi": false, "singleQuote": true, "printWidth": 100 }

SchemaStore hosts schemas for hundreds of well-known files, and VS Code associates common names such as package.json and tsconfig.json automatically, so a misspelled "dependencies" is underlined immediately. The next lesson shows how to write a schema for your own application's config so your users get the same experience.

JSON, JSONC, JSON5, YAML or TOML?

| Format | Comments | Trailing commas | Multiline strings | Typical use | |--------|----------|-----------------|-------------------|-------------| | JSON | no | no | no | package.json, APIs, data exchange | | JSONC | yes | yes | no | tsconfig.json, VS Code settings | | JSON5 | yes | yes | yes | Some build tools; unquoted keys, single quotes | | YAML | yes | n/a | yes | Docker Compose, GitHub Actions, Kubernetes | | TOML | yes | n/a | yes | pyproject.toml, Cargo.toml, .NET tooling |

Choose plain JSON when machines will read or write the file and when interoperability matters. Choose YAML or TOML for files humans author by hand that benefit from comments and less punctuation, keeping in mind YAML's own traps such as indentation sensitivity. Whatever you choose, keep secrets out: API keys belong in environment variables or a secrets manager, never in a committed file.

Quick Quiz
Question 1 of 3

What happens if you add a `// comment` to `package.json`?

Key Takeaways

  • package.json is strict JSON; use npm pkg set/get for safe edits and a "//" key for notes.
  • tsconfig.json, VS Code settings and similar files are JSONC: comments and trailing commas are tolerated by their tools but not by JSON.parse.
  • A $schema property gives any JSON config file editor validation and autocomplete.
  • JSON5, YAML and TOML trade strictness for readability; pick them for hand-written configs, plain JSON for machine-exchanged data.
  • Never commit secrets in configuration files; load them from the environment.

Next lesson: JSON Schema and Validation — describe the exact shape a JSON document must have and validate data automatically.

JSON Configuration Files: package.json, tsconfig.json and JSONC - JSON | CodeYourCraft | CodeYourCraft