# Teal's tl compiler: typed Lua that ships as a single tl.lua file

> tl adds optional static types to Lua and compiles the result back to plain Lua. Here is how the compiler is structured, how to install it with LuaRocks, and where the type checker stops being useful.

**teal-language/tl** — The compiler for Teal, a typed dialect of Lua

- Repository: https://github.com/teal-language/tl
- Website: https://teal-language.org
- Stars: 2,823 · Forks: 163
- Language: Lua
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/teal-language-tl

## What tl solves for Lua codebases

Lua gives you tables, closures and a small standard library, and nothing that tells you a field is missing until the line that reads it executes. Teal is a typed dialect of Lua, and tl is its compiler. The target audience is people who already write Lua and want type errors reported before the program runs, without switching runtimes. The README is explicit that the compiler works with Lua 5.1 through 5.4, including LuaJIT, so the output is ordinary Lua that any of those interpreters can load. That constraint shapes everything: Teal is not a new VM and not a superset with new runtime semantics. Annotations are checked and then stripped, which is why the compiler can hand you a .lua file that looks like something you would have written by hand. The project itself is written in Teal, according to the README, which means the compiler is one of its own larger users.

## A single tl.lua file, a precompiled environment, and a package loader

The README states that the core compiler has no dependencies and is implemented as a single tl.lua file you can load into your projects. That file is generated from tl.tl, and the Makefile shows the bootstrap: precompiler.lua is produced by running the stable tl over precompiler.tl, and that script emits teal/precompiled/default_env.lua from the prelude and stdlib declaration files. The default environment is therefore baked in rather than parsed on every startup. Around the compiler sit teal/check/* for type checking, teal/gen/lua_generator.tl for code generation, and teal/package_loader.tl plus teal/loader.tl for runtime loading. The loader path is the interesting one: calling tl.loader() hooks the package loader so require() can compile .tl files on the fly. That is a runtime dependency on the compiler being present in the process. Pre-compiling with tl gen removes it, and the README presents both as valid choices. The trade is startup cost and a compiler in production against a build step you have to run.

## Installing tl with LuaRocks and running a first check

The README's install path is LuaRocks. Install Lua and LuaRocks first, then:

```bash
luarocks install tl
```

That should place a tl command on your $PATH. If the LuaRocks-installed binaries are not on your path, the README points at eval $(luarocks path). Pre-compiled binaries for Linux x86_64 and Windows x86_64 are also published on the releases page, and those packages contain a standalone executable that runs Teal programs without a separate Lua installation. For a first real use, write a small module and check it:

```bash
tl check module.tl
```

According to the README, tl check type checks a Teal module, reports any errors and quits. When you want the Lua output instead, tl gen checks for syntax errors and writes a module.lua with all type annotations stripped. tl run script.tl executes a Teal script directly, and tl warnings lists every warning the compiler can produce, which is worth reading once so you know what the checker will complain about. Compiler options can go on the command line or in a tlconfig.lua file at the project root. For multi-file work the README recommends Cyan, the build tool designed for Teal, rather than invoking tl per file.

## Where the type checker stops helping

Teal's types describe Lua values, so anything Lua cannot express is also outside the checker's reach. The README says declaration files are the mechanism for annotating third-party Lua libraries, and it points to the separate teal-types repository as the collaborative home for those files. That is the practical limit: a library without a declaration file is either untyped in your project or typed by a file you write and maintain yourself. The README does not document rollback or migration behaviour, so there is no stated path for reverting a project from Teal to Lua beyond keeping the generated .lua output. Loading .tl files at runtime through tl.loader() also means the compiler ships with your program, which is the wrong choice when startup time or deployment size matters. And if you need a typed language with a broad library ecosystem, Teal's ecosystem is Lua's ecosystem plus whatever declarations exist, not a replacement for it.

## Teal against plain Lua with a linter

The realistic alternative is untyped Lua with a static analysis tool such as Luacheck, plus runtime assertions. The difference in approach is where the information lives. A linter infers from usage and flags suspicious patterns; Teal requires the developer to write the types down, and tl checks those declarations against the code. That makes Teal more precise on module boundaries, where a function's parameter and return types are stated rather than guessed, and more work up front. It also means the checker can only be as good as the declarations you and teal-types provide. If your Lua code is mostly small scripts with no shared interfaces, the annotation cost buys little. If it is a library with callers you do not control, stating the interface in a .d.tl file is the part of Teal that earns its keep.

## Maintenance, releases and the MIT licence

The last push to the default branch was on 2026-09-15, and the most recent release listed is v0.24.8 from 2025-10-13, following v0.24.7 and v0.24.6 earlier in 2025. The version numbers are still in the 0.24 range, so the project does not present itself as API-stable. The compiler is bootstrapped from itself, as the Makefile's multi-stage precompiler and _temp/%.lua.1 and _temp/%.lua.2 rules show, which means upgrading tl can require regenerating teal/precompiled/default_env.lua before the suite runs. That is a real upgrade cost for anyone building from source rather than installing a release. The licence is MIT, the same as Lua, per the README. MIT is permissive and compatible with Lua's own terms, but the repository also bundles third-party declaration files such as argparse.d.tl and lfs.d.tl, and the README does not state their provenance, so check those files if you redistribute them. Nothing here is legal advice.

## Conclusion

Adopt tl if you maintain Lua code that outgrew untyped tables and you want type errors reported before runtime, without giving up the Lua runtime or your existing modules. Skip it if you need a language with a large typed ecosystem or you cannot accept that declaration files for third-party libraries are maintained separately in teal-types. Before committing, run tl check on one real module with your project's tlconfig.lua in place, then run tl gen on it and diff the generated Lua against what you expected, so you see exactly which annotations survive and which are stripped.

## FAQ

### What is the tl compiler for Teal?

tl is the compiler for Teal, a typed dialect of Lua. It type checks .tl files, runs them, and generates plain Lua with the type annotations stripped.

### How do I install tl?

The README says to install Lua and LuaRocks, then run luarocks install tl, which should put a tl command on your $PATH. Pre-compiled binaries for Linux x86_64 and Windows x86_64 are also available on the releases page.

### Which Lua versions does Teal support?

According to the README, Teal works with Lua 5.1 through 5.4, including LuaJIT. The Makefile's TLGENFLAGS uses --gen-target=5.1 for the self-build.

### What do the tl check and tl gen commands do?

tl check type checks a Teal module, reports any errors and quits. tl gen checks for syntax errors and generates a .lua file in plain Lua with all type annotations stripped.

### Can I require .tl files from Lua at runtime?

Yes. The README shows requiring the tl module and calling tl.loader(), after which require() can load and compile .tl files on the fly. The alternative is pre-compiling the .tl files into .lua first.

## Sources

- [License: MIT](https://github.com/teal-language/tl/blob/main/LICENSE)
- [Project website](https://teal-language.org)
- [README](https://github.com/teal-language/tl/blob/main/README.md)
- [Releases](https://github.com/teal-language/tl/releases)
- [teal-language/tl on GitHub](https://github.com/teal-language/tl)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/teal-language-tl
