TypeScript
elements man typescript Read as markdownElements is the first build tool to compile the TypeScript compiler, the Go implementation, directly into its own binary. Type checking is a phase of the build, running in the same process against the same in-memory source graph as compilation, so a save is checked, compiled, and hot reloaded in a few milliseconds. Both targets are checked, the browser and the server, each against the types it actually has.
One program, one graph
Every source in a project has a version derived from its content and the versions of everything it imports. The checker consults that version like every other phase of the build: a file whose version has not moved is not rechecked, and a change deep in the graph rechecks exactly the cone that depends on it. The same graph drives the build cache, the test runner, hot reload, and the deploy, so type checking, compilation, and release agree on one version of every file.
Checking runs incrementally inside the build loop, on the same thread that watches your files. A single-file save typically type checks, compiles, and hot reloads in a few milliseconds.
The Elements languages are TypeScript
Elements HTML templates and JSOC config files are implemented on top of the
TypeScript compiler's own binder, symbol table, and checker, not beside them. A
template attribute is a TypeScript declaration. A template name resolves
through the normal symbol table. The expressions inside {} are checked
against the surrounding scope by the same checker that checks a .ts file,
with the same error messages. There is no second type system to learn, and no
seam where TypeScript ends and Elements begins.
<Comment (comment: Comment, private editing: boolean = false)>
<p>{comment.text.toUpperCase()}</p>
<p>{comment.txet}</p> <!-- error: Property 'txet' does not exist on type 'Comment' -->
</Comment>
Two targets, one source
A file is checked for every target it reaches. Server code sees Node's types
and the server half of @elements/app; browser-reachable code sees the DOM and
the browser half. A server-only call such as sql() made from code the browser
can reach is a compile error at the call site, so a query or a secret cannot
reach the browser by accident. You do not annotate anything; the compiler
follows the call graph. See rpc for the boundary and async for how
sync-style calls type check without await.
Options
TypeScript options live under build.typescript in config.jsoc, a flat
mirror of tsconfig's compilerOptions limited to the options Elements honors.
Strict checking is on. There is no tsconfig.json in an Elements project and
you should not add one.
build: {
typescript: {
lib: ["es2022", "dom"],
},
},
Full config syntax: config.
Editors
The project server speaks the Language Server Protocol, so editors get
completions, diagnostics, go-to-definition, and rename for .ts files, HTML
templates, and JSOC alike, from the same checker the build uses. It replaces
tsserver. VS Code and its derivatives get this automatically; the extension
is installed when you install Elements. For vim and neovim see vim.
Diagnostics
Type errors are build errors. They appear in elements build, in
elements build -json as diagnostics with a path and a 1-based loc, and in
the editor, all from one check. A build with a type error anywhere does not
release, and neither do the tests it would have gated. See build.
Related
build: the loop the checker runs inside.html: the template language the checker understands.config:build.typescript.async: the sync-style transform and how it types.