testImportGlobalAugmentation
A declare global augmentation is a definition of its own (<file>.global) that every check in the codebase
includes: code relying on it typechecks whether or not it imports the augmenting file, scratch files see it, and
editing it checks the new version alone.
import { okIn, tempDir } from "#codebase/tcmts/cli/test/e2e/harness"; import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; export const testImportGlobalAugmentation = () => { const dir = tempDir("augment"); const lib = tempDir("augment lib"); const tcm = (...args: string[]) => okIn(dir, ...args); tcm("init"); const write = (file: string, text: string) => { fs.mkdirSync(path.dirname(path.join(lib, file)), { recursive: true }); fs.writeFileSync(path.join(lib, file), text); }; write( "tsconfig.json", JSON.stringify({ compilerOptions: { strict: true, lib: ["ESNext"], target: "ES2022" } }), ); write( "src/errors.ts", `export const exitCode = "~lib/exitCode" as const; /** What errors may carry. */ declare global { interface Error { readonly [exitCode]?: number; readonly hint?: string; } } export const codeOf = (e: Error): number => e[exitCode] ?? 1; `, ); // relies on the augmentation without importing the file it's in write("src/hints.ts", `export const hintOf = (e: Error): string => e.hint ?? "none";\n`); assert.match(tcm("import", path.join(lib, "src"), "--into", "lib"), /\+ new 4/); assert.match(tcm("view", "lib.errors.global"), /declare global \{\n\s+interface Error/); assert.match(tcm("verify"), /verified \d+ definitions/); fs.writeFileSync( path.join(dir, "scratch.ts"), `// tcm: namespace app import { codeOf } from "#codebase/lib/errors"; import { hintOf } from "#codebase/lib/hints"; export function main() { const e = new Error("x"); console.log("errors", codeOf(e), hintOf(e), e.hint === undefined); } `, ); tcm("add"); assert.match(tcm("run", "app.main"), /errors 1 none true/); // a new version of the augmentation is checked without the stored one, which declares the same members tcm("edit", "lib.errors.global"); const scratch = path.join(dir, "scratch.ts"); fs.writeFileSync( scratch, fs .readFileSync(scratch, "utf8") .replace( "readonly hint?: string;", "readonly hint?: string;\n readonly retries?: number;", ), ); tcm("update"); fs.writeFileSync( scratch, `// tcm: namespace app\nexport const retriesOf = (e: Error): number => e.retries ?? 0;\n`, ); tcm("add"); assert.match(tcm("run", "app.retriesOf", "--", "{}"), /0/); }