Journal
Sections
Reading settings
No voice for this language in this browser.
More voices
Code and English terms
Off: the page’s voice reads everything, with no pause between two voices.
No voice for this language in this browser.
More voices
More voices: Microsoft Edge has natural online voices, and Windows (Settings › Time & language › Speech), macOS and Android install others.
Progress
Section titled “Progress”- TypeScript 7.0.2 pinned in the course’s own
package.jsonand lock file, with@types/node24.13.4 and tsx 4.23.13 - CI:
tscon the project and on each error snippet, every example and solution run with Node.js 24.21.0, the C# and Java comparisons compiled and run, all compared with their expected output on three OSes - Lesson 1: the compiler and the tooling
- Lesson 2: structural typing
- Lesson 3: unions and narrowing
- Lesson 4: generics
- Lesson 5: type-level programming
The TypeScript compiler at 7.0.2 — the Go port — with Node.js 24 and npm 11. Half of these rows are deliberate changes that break an assumption rather than defects, and the Status column says which. The fourth row is the one place where the author expected an error, did not get one, and the compiler turned out to be right.
There is no Experiments table: that fourth row is the journal’s only prediction written before its test, and a table of one row would read like a section that failed to fill.
| Expected | What happens | Where | Measure | Status |
|---|---|---|---|---|
tsc --noEmit with errors returns the same exit code it always has |
The code changed between 6.0 and 7.0 | tsc 6.0.3 against 7.0.2 | 6.0.3 returns 2, 7.0.2 returns 1. In 7.0.2, 1 means errors prevented the output and 2 means the output was written despite them | By design, a breaking change. A CI step testing for 2 breaks on the upgrade; test for non-zero 2026-09-15 |
tsc file.ts next to a tsconfig.json quietly ignores the config |
Since 6.0 it is an error | tsc 6.0 and later | TS5112. --ignoreConfig restores the old behaviour; the course builds a small tsconfig per error snippet instead |
By design 2026-09-15 |
| Union members print in the order they were declared | They do not, and the order changed between versions | tsc 5.9.3 against 7.0.2 | On GA’s ForceRadiant.tsx: `“warning” |
“error” |
A wrong out variance annotation is refused |
interface Mislabeled<out T> { accept(value: T): void } compiles |
tsc 7.0.2 | Method parameters are bivariant, so T in that position satisfies both annotations. C# reports the same interface as CS1961. The snippet was replaced with in T on a method returning T, which tsc does catch as TS2636 |
By design. The author expected an error and the compiler was right — the lesson changed, not the compiler 2026-09-15 |
Array.isArray narrows an unknown safely |
It narrows to any[], so a property access compiles with no check at all |
tsc 7.0.2, the lib declaration of Array.isArray |
In lesson 2’s exercise-2 solution, item.name compiled without a check, and tsc never asked for the typeof checks that make it correct |
By design, and worth knowing 2026-09-15 |
| A stable API is silent | module.stripTypeScriptTypes still prints an ExperimentalWarning, although type stripping itself is stable and silent |
Node.js 24.21.0 | The warning, on every call | Reproduced, not reported — the best upstream candidate in this journal 2026-09-15 |
| Node’s error points at the line as written | The source line in the message has spaces where the types were | Node.js 24.21.0 type stripping | const guitarSource = instrumentSource; — that is how stripping preserves line and column numbers |
By design 2026-09-15 |
dotnet run file.cs prints the compiler’s warnings on every run |
It builds incrementally, so a second run with an unchanged source prints them once and never again | .NET 10 file-based programs | The first CI run failed on all three OSes on two files: CS8602 and CS8509 were in the CI’s output and not in the author’s. Fixed with dotnet clean then dotnet run --no-cache |
Reproduced in CI and locally, not reported 2026-09-14 |
| A newer compiler reports the same errors | TypeScript 7 finds more of them, much faster | tsc 5.9.3 against 7.0.2 on ga-react-components |
180 errors in 14.7 s with 5.9.3; 197 in 1.9 s with 7.0.2. New codes: TS2591, because types now defaults to []; TS2871 “this expression is always nullish”; TS2550 for .at() with lib at ES2020 |
Reproduced. The journal records its own caveat: the dependency versions came from a non-frozen install 2026-09-15 |
| npm runs install scripts | npm 11.19 no longer runs them by default | npm 11.19 with tsx 4.23.13 | npm warn install-scripts esbuild@0.28.2 (postinstall: node install.js). tsx works anyway on the three OSes, because esbuild’s binary arrives as an optional platform package |
By design, a changed default 2026-09-14 |
| TypeScript 7.0 offers a programmatic API | It has none yet; tools that load the compiler as a library use @typescript/typescript6, a compatibility package that provides 6.0 with a tsc6 command |
TypeScript 7.0 | Read in the documentation, not exercised — the course did not need it | By design, a known gap in the Go port 2026-09-14 |
| A lock file written on Windows needs rewriting on Linux | It lists all twenty platform packages as optional dependencies, so one file works on three systems | typescript 7.0.2, the Go port | @typescript/typescript-win32-x64 locally; the CI step lists typescript-linux-x64 and typescript-darwin-arm64 |
By design, and it is what makes the three-OS CI cheap 2026-09-14 |
2026-09-14 — Installing TypeScript 7.0.2
Section titled “2026-09-14 — Installing TypeScript 7.0.2”npm view typescript versiongives 7.0.2, the Go port, published on 2026-07-08. Thetypescriptpackage is now small: npm installs the compiler as one package per platform,@typescript/typescript-win32-x64on my machine, and the CI’s info step liststypescript-linux-x64on Linux andtypescript-darwin-arm64on macOS. The lock file lists all twenty platform packages as optional dependencies, sonpm ciworks on the three OSes from the one lock file written on Windows.- TypeScript 7.0 has no programmatic API yet. Tools that load the compiler as a library can use
@typescript/typescript6, a compatibility package that provides TypeScript 6.0 with atsc6command; I didn’t need it for the course. - The course pins its versions in
code/typescript-for-csharp-java/package.json, not in the site’s: the site itself has notypescriptdependency. - npm 11.19 no longer runs install scripts by default. Installing tsx printed
npm warn install-scripts esbuild@0.28.2 (postinstall: node install.js), and tsx works anyway, on the three OSes: esbuild’s binary comes from a platform package installed as an optional dependency.
2026-09-14 — The CI
Section titled “2026-09-14 — The CI”typescript-examples.ymlinstalls Node.js 24.21.0, .NET 10 and Java 25, runsnpm ciin the course folder, thencheck.shwithREQUIRE_COMPARE=1, so that a missingdotnetorjavafails the run instead of skipping the comparisons.check.shrunstsconce on the whole project, which must pass, and once per error snippet, with a generatedtsconfigthat extends the course’s and lists that one file; a snippet can ask for extra options with a// tsc options:comment, as lesson 2’snoUncheckedIndexedAccessdoes.normalize.mjs, adapted from the JavaScript course, makes paths relative and removes stack frames and process IDs.- The first run failed on the three OSes, on two files only, and for the same reason: the C# warnings
CS8602andCS8509were in the CI’s output and not in mine.dotnet run file.csbuilds a file-based program incrementally, and a second run with an unchanged source doesn’t call the compiler, so its warnings are printed only once.check.shnow runsdotnet cleanon the file beforedotnet run --no-cache, and the outputs captured on Windows match on Linux and macOS. The next run passed on the three OSes in 2 minutes 41 seconds, Windows being the slowest job.
2026-09-15 — Surprises while writing lessons 1-4
Section titled “2026-09-15 — Surprises while writing lessons 1-4”tsc’s exit code changed between 6.0 and 7.0. With --noEmit and errors, tsc 6.0.3 returns 2, and 7.0.2 returns 1. In 7.0.2, 1 means that errors prevented the output, with noEmit or noEmitOnError, and 2 that the output was written despite errors, which lesson 1 shows with l01-emit. A CI step that tests $? -eq 2 would break on the upgrade; test for a non-zero code.
tsc file.ts next to a tsconfig.json is an error since 6.0. TS5112 refuses to ignore the configuration silently, as older versions did; --ignoreConfig restores the old behavior. check.sh builds a small tsconfig for each error snippet instead.
Union members don’t print in declaration order. The same comparison in GA’s ForceRadiant.tsx prints "warning" | "error" | "unknown" | "contradictory" with 5.9.3 and "contradictory" | "error" | "unknown" | "warning" with 7.0.2. The 6.0 release notes explain it: TypeScript 7 sorts types by content so that parallel checkers agree. Lesson 3’s expected outputs are those of 7.0.2 only.
A wrong out annotation compiles. I wrote interface Mislabeled<out T> { accept(value: T): void } for lesson 4’s error snippet, expecting an error, and tsc 7.0.2 accepted it: accept is a method, method parameters are bivariant, and T in that position satisfies both annotations. C# reports the same interface with CS1961. The snippet now uses the mistake that tsc does catch, in T on a method that returns T (TS2636).
Array.isArray brings any back. In the solution of lesson 2’s second exercise, the value was unknown, and Array.isArray(value) narrowed it to any[]: item.name compiled without a check. The solution’s typeof checks make it correct; tsc didn’t ask for them. Lesson 2 points it out.
Node.js prints the stripped line. When a .ts file fails at run time, the source line in Node.js’s message has spaces where the types were, as in lesson 4’s const guitarSource = instrumentSource;. That is how type stripping keeps line and column numbers.
module.stripTypeScriptTypes still prints an ExperimentalWarning in 24.21.0, although type stripping itself is stable and silent; lesson 1 shows the warning.
2026-09-15 — What tsc found in GuitarAlchemist/ga (a826864)
Section titled “2026-09-15 — What tsc found in GuitarAlchemist/ga (a826864)”I cloned GuitarAlchemist/ga at a826864 into a scratch folder, installed the two front ends, and ran tsc with 5.9.3, the version that the component library’s pnpm-lock.yaml resolves, and with 7.0.2.
- Names used and never defined.
Apps/ga-client/src/components/Chat/ChatInterface.tsxusesVIRTUALIZATION_THRESHOLD(lines 69 and 219) andVirtualizedMessageList(lines 254 and 255), and nothing defines or imports them:TS2304. The/ai-copilotroute ofApp.tsxloads that component, so the page should throw aReferenceErrorwhen it renders (to verify in a browser). Reproduction:cd Apps/ga-client && npm ci && npx tsc -b --pretty false | grep ChatInterface. This looks like a bug worth an issue. - Type errors don’t fail the build. Both front ends build with
vite build, which strips types without checking them;ga-clientreports 346 errors withtsc -b(165 of themTS6133, unused variables), andga-react-components186. Atsc --noEmitstep in CI would have caught the missing names. - A stale lock file. In
ReactComponents/ga-react-components,pnpm install --frozen-lockfilefails withERR_PNPM_OUTDATED_LOCKFILE: 21 dependencies ofpackage.jsonare missing frompnpm-lock.yaml, and the versions of@react-three/dreiand@react-three/fiberdiffer. I installed without--frozen-lockfile, so the component library’s error counts may depend on the versions I got. - Statuses that the type rules out.
ForceRadiant.tsx, lines 721 and 725, compares aGovernanceHealthStatuswith'ok'and'critical', which the union doesn’t contain (TS2367), andDataLoader.ts, lines 276-278, passes a SignalR message’shealthStatus: stringthroughas unknown as GovernanceNode. Either the union is missing two statuses or the comparisons are dead code (to verify in GA’s hub). Line 1464 of the same file compares a signal severity,'info' | 'warning' | 'emergency', with'critical'. Lesson 3 reduces the first case. noImplicitAny: falsenext tostrict: trueinga-react-components/tsconfig.app.json. Turning it back on adds only four errors, inBSPDoomExplorer.tsxandIxqlFormPanel.tsx; lesson 2 lists them.- Unchecked data. The component library has 34
as unknown as, 42 calls toJSON.parseand 18as any. The camera is restored fromlocalStoragewithJSON.parse(saved) as { px: number; … }(ForceRadiant.tsx, line 3558),loadQueue<T>returnsJSON.parseas aT[](CourseViewer.tsx, line 152), andga-client’sisApiResponse<T>checks two property names before promising anApiResponse<T>, withjson as Tas its fallback (musicService.ts, lines 17-49). Lessons 3 and 4 and their exercises write the checked versions. - TypeScript 7 finds more.
tsc -p tsconfig.app.jsonon the component library gives 180 errors in 14.7 seconds with 5.9.3 and 197 in 1.9 seconds with 7.0.2. The new errors are Node.js names in two scripts (TS2591, becausetypesnow defaults to[]),TS2871(“this expression is always nullish”) inBrainstormPanel.tsxline 40 andGitHubPollingManager.tsline 48, andTS2550for.at()inChatWidget.tsxline 1254, withlibset to ES2020; 5.9.3 reported neither code. - Small things.
ga-client/tsconfig.jsonhas"sourceMaps": trueat its top level, wheretscignores it; the option issourceMap, insidecompilerOptions.src/components/PrimeRadiant/index.tsin the component library exportsRemediationActiontwice (TS2300, lines 101 and 129), andThreeFretboard.tsxline 780 uses aGuitarModelStyletype that doesn’t exist.ga-client’sShowcasePanel.test.tsxuses Node.js’sglobal, which the browser project’s types don’t declare.
2026-09-15 — What tsc found in this site (8ba378e)
Section titled “2026-09-15 — What tsc found in this site (8ba378e)”npx -p typescript@7.0.2 tsc --noEmit at commit 8ba378e, with the site’s tsconfig.json, reports three errors, the same with 6.0.3. None breaks the site.
astro.config.mjs, line 146: the sidebar imported fromsrc/streeling-sidebar.jsondoesn’t match Starlight’sSidebarItemUserConfig, because the inferred union of its entries addsfr?: undefinedto the entry that has only a Spanish translation. Lesson 3 explains the inference.code/javascript-for-csharp-java/errors/l04_private_outside.js: the site’stsconfig.jsonincludes**/*, sotscchecks the course code, including an error snippet that is wrong on purpose. The TypeScript course’serrors/*.tswill be picked up the same way; excludingcode/in the site’stsconfig.jsonwould keep editors andtscon the site’s own files.src/content.config.ts:astro:contentis declared only afterastro sync.
To verify
Section titled “To verify”- The
ReferenceErroron GA’s/ai-copilotpage, in a browser. - Whether GA’s governance hub sends
okandcriticalas health statuses. - What GA’s
ForceRadiantdoes with a saved camera that lacks a coordinate. new[] { 1, "two", null }in C#, quoted in lesson 2 as refused for lack of a best common type.- The installation commands of lesson 1 on Linux and macOS outside CI.