Note: This is a custom experimental fork of TypeScriptToLua modified by PIKO8. It introduces a compiler-level
@inlineoptimization pass for micro-optimizations and zero-overhead lambdas.
The main goal of this fork is to bring Kotlin-style zero-overhead @inline functions to TypeScriptToLua. Unlike experimental community plugins, this feature is baked directly into the compiler engine, supporting deep cross-file analysis and complex control flows.
- Functions marked with JSDoc
/** @inline */are completely unwrapped into the calling expression/statement. - Works seamlessly across different files and modules via strict TS Symbol aliasing resolution.
- Fully supports inlining functions that accept other functions (lambdas/callbacks) as arguments (e.g., custom
filter,map,forEach). - Arrow functions and inline expressions are embedded into loops and conditions without creating closures or allocating anonymous tables in Lua.
- Lua 5.2+, JIT, Luau: Translates deep
returnstatements in complex multi-return lambdas into high-performance nativegotojumps with macro hygiene (guaranteed unique labels). - Lua 5.1 / Universal: Automatically downgrades complex control flow into efficient state-machine blocks using temporary execution flags (
____done_...), ensuring 100% runtime compatibility.
- Triivial functions (single trailing return expressions) skip block overhead and flatten directly into equations or native multiple assignments.
- Perfect cooperation with
LuaMultiReturn/$multicompiler macro.
inlineGenerateComment: (boolean) Generates-- Start inline [name]annotations directly in the emitted Lua files to simplify debugging.inlineRemoveDefault: (boolean) Globally toggles whether to strip the original inline function declarations from the compiled output. Can be overridden per function via/** @inline toggle */.
/** @inline */
function filter<T>(arr: T[], pred: (x: T) => boolean): T[] {
const result: T[] = [];
for (const item of arr) {
if (pred(item)) result.push(item);
}
return result;
}
export function test() {
const data = [1, 2, 3, 4, 5, 6];
// Inlining simple conditions
const evens = filter(data, n => n % 2 == 0);
// Inlining heavy block expressions with early returns
const withBlock = filter(data, n => {
if (n == 3) return true;
return n > 4;
});
return [evens, withBlock];
}function ____exports.test(self)
local data = {1, 2, 3, 4, 5, 6}
local evens
do
local result = {}
for ____, item in ipairs(data) do
if item % 2 == 0 then
result[#result + 1] = item
end
end
evens = result
end
local withBlock
do
local result = {}
for ____, item in ipairs(data) do
local ____lambdaResult_0 = nil
do
if item == 3 then
____lambdaResult_0 = true
goto ____inline_end_1
end
____lambdaResult_0 = item > 4
::____inline_end_1::
end
if ____lambdaResult_0 then
result[#result + 1] = item
end
end
withBlock = result
end
return {evens, withBlock}
end💡 Note on Variable Naming: To make this example easy to read, some variable names have been manually cleaned up. In actual generated Lua code, the compiler enforces strict macro hygiene by automatically renaming local variables and arguments inside inline blocks (e.g., transforming
iteminto____item_inline_1). This ensures complete scope isolation and completely prevents name collision bugs with the surrounding code!
This inliner was developed as a powerful custom extension of the compiler. While it passes all core integration tests, please keep the following trade-offs and architectural quirks in mind:
- The Issue: If you use inline functions inside logical conditions (e.g.,
if (isValid() && fetchProps())), the compiler hoists evaluation do-blocks before executing theifstatement itself. - The Result: Both inline functions will always be executed, even if the first one returns
false. This can cause unexpected side-effects. It is highly recommended to store inline function results in local variables manually before using them in complex conditional logic.
- Deeply nested inlining of complex statements—especially with state-machine generation for older Lua 5.1 targets—can complicate accurate runtime line debugging.
- To make code tracking easier during development, always enable the
--inlineGenerateComment trueflag.
- About 70% of this compiler fork's logic was built in collaboration with AI (Qwen) directly inside the IDE.
- Because of this AI-driven approach, some edge cases might still be unhandled, and deep internal refactoring can be highly complex. However, it completely fulfills its goal for practical, micro-optimization tasks! "It works on my machine" ™️ — use it with care and feel free to submit PRs for any bugs you find.
A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!
Large projects written in Lua can become hard to maintain and make it easy to make mistakes. Writing code in TypeScript instead improves maintainability, readability and robustness, with the added bonus of good tooling support (including ESLint, Prettier, Visual Studio Code and WebStorm). This project is useful in any environment where Lua code is accepted, with the powerful option of simply declaring any existing API using TypeScript declaration files.
To install TypeScriptToLua add the typescript-to-lua npm package:
$ npm install -D typescript-to-luaThis package includes the tstl command line application, which can be used similarly to tsc:
$ npx tstl
For more information, check out Getting Started in our documentation.
