Introduction — tcm-ts

Introduction

tcm-ts keeps your TypeScript in a codebase instead of a folder of files. Each function, type and constant is stored by the hash of its code, and names are labels pointing at hashes.

You still write ordinary TypeScript, in scratch files. When it typechecks, tcm add saves it.

Why

  • Renames are free. tcm mv lib.parse lib.parseConfig moves a label. No code is edited.
  • Changes carry through. tcm update re-checks everything that uses what changed. What still typechecks follows along; what doesn't goes on a todo list, with the reason.
  • Nothing to build. Node runs the stored code directly. Tests and lint results are cached by hash, and shared with tcm push and tcm pull.
  • Less to manage. Apps bundle only what they reach, there are no circular imports, and one codebase holds any number of apps and packages, with no package.json to maintain.
  • History by meaning. tcm diff shows renames as renames, and reformatting isn't a change.
  • Docs that stay right. Links in doc comments follow renames, and examples in them are run.
  • Web apps without an API layer. Browser code calls server functions by importing them, and tcm works out what runs where. Calls go by hash, so a page never calls the wrong version of the server.

Each claim, and where it stops: what tcm does away with.

It's Unison's codebase model for plain TypeScript: no new language, and Node runs the code as it is.

How it's different

A small shop app as a JavaScript project: code in files, in folders, in packages, and tools that each read the files.

The shop app as a JavaScript project: definitions in files, folders and packages, six tools, and four outputs, with five problems marked[close]

The same app as a codebase: each definition on its own, and each output built from what it starts from reaches.

The same app as a codebase: names pointing at hashes, the definitions and their references, and four outputs, each starting from one definition, with what became of the five problems[close]

Change one value, and a project redoes every file that imports its file. A codebase redoes only what reaches it.

The project as TAX_RATE changes: all of @shop/web, five tools and both bundles are redone[close]

The codebase as TAX_RATE changes: five definitions get new hashes, one test runs, and the server and the npm package are unchanged[close]

What it looks like

// scratch.ts
/** Square a number. */
export const square = (x: number): number => x * x;

square(12);
$ tcm check
scratch.ts
  + new       square : (x: number) => number

    7 │ square(12)
      ⧩ 144

$ tcm add
  + new       square : (x: number) => number

square(12) on its own line is a watch expression: tcm check shows its value. Other files use square with import { square } from "#codebase".

Next

Built from c482a14e