Use TypeScript declaration files for existing Lua APIs
.d.ts), which allows for static checking and improved IDE support (like refactoring and autocomplete) during Lua application development.website·Indexed 29 days ago
https://typescripttolua.github.io/Documentation for TypeScriptToLua (TSTL), a transpiler that converts TypeScript to Lua. It includes guides on installation, project setup, high-level and printer APIs, plugin development, and language extensions like LuaMultiReturn. The docs cover feature support, JSX integration as of version 0.42.0, compiler annotations such as @compileMembersOnly, and the use of declaration files for external Lua APIs.
.d.ts), which allows for static checking and improved IDE support (like refactoring and autocomplete) during Lua application development.There are two types of libraries that can be published via npm for use with TypeScriptToLua:
LuaPrinter class is responsible for taking a Lua AST and printing it to a string. It implements the visitor pattern, where methods visit specific AST nodes to produce SourceNode objects. This process automatically generates the correct mappings for the resulting source map.// Example instantiation
const printer = new LuaPrinter(options, emitHost, fileName);
const result = printer.print(block, luaLibFeatures);
// result contains:
// result.code: The generated Lua code string
// result.sourceMap: The source map string
// result.sourceMapNode: The SourceNode object.d.ts extension and contain 'ambient' code—code that exists only at compile-time to inform the TypeScript compiler about the types of external functions, modules, and variables in the target Lua environment. Ambient declarations are not emitted into the generated .lua files. While typically placed in .d.ts files, ambient declarations can also be written inside standard .ts files.__call) and have static methods, define a constructor interface that includes both a call signature and the method definitions.interface Box {
get(): string;
}
interface BoxConstructor {
(this: void, value: string): Box;
getInstance(): Box;
}
declare var Box: BoxConstructor;
// Usage
const box = Box("foo");
box.get();
Box.getInstance().get();To enable type checking for external Lua functions and variables, install the relevant type declaration package from npm and add the package name to the types array within compilerOptions in tsconfig.json.
Official declarations for the Lua standard library are available via the lua-types package, which is useful for low-level Lua operations.
tsconfig.json to allow JSON module resolution and use the node module resolution strategy.{
"compilerOptions": {
"moduleResolution": "node",
"resolveJsonModule": true
}
}types array in tsconfig.json.# Publishing steps
npm init
npm login
npm publish --dry-run # Preview files to be published
npm version 0.0.1 # Update version in package.json
npm publish # Final publish
# Installation step
npm install <declarations> --save-dev// tsconfig.json
{
"compilerOptions": {
"types": ["declarations"]
}
}When publishing your tstl library:
package.json and README.md are always published regardless of the files array.devDependencies are not available at runtime.tsconfig.json file does not need to be published as it is not used by the consumer.Recommended workflow:
npm publish --dry-run to verify the file list.npm publish to upload the package.npm publish --dry-run
npm publishfor ... in to iterate over an array is not allowed in TSTL. Use a for ... of loop instead.export = syntax in the declaration file. In the TypeScript code, use the import * as syntax to access the array.-- things.lua
return {
{ foo = 123, bar = 456 },
{ foo = 789, bar = 987 },
}// things.d.ts
interface Thing {
foo: number;
bar: number;
}
declare const things: Thing[];
export = things;
// main.ts
import * as things from "./module";
print(things[0].foo); // Prints "123"import statements can be placed inside ambient modules and namespaces to provide type dependencies for specific functions.import "./lib";
// All global declarations in lib will be included with this file
export { Player } from "./Entities";
// The Player declaration is re-exported from this file
declare module "mymodule" {
import * as types from "types";
export function getType(): types.Type;
}