Types¶
Built-in types¶
-
class nil¶
The type
nil
has one single value, nil, whose main property is to be different from any other value; it usually represents the absence of a useful value.
-
class boolean¶
The type
boolean
has two values, false and true. Bothnil
and false make a condition false; any other value makes it true.
-
class number¶
Lua uses two internal representations for numbers: integer and float. It has explicit rules about when each representation is used, but it also converts between them automatically as needed.
EmmyLua, on the other hand, allows explicitly annotating which representation is expected. The
number
type can contain both integer and float values. Theinteger
is a sub-type ofnumber
, and only allows integer values.See also
Lua’s manual on value types.
-
class integer¶
The type
integer
is a sub-type ofnumber
that only allows numbers with integer representation.
-
class userdata¶
The type
userdata
is provided to allow arbitrary C data to be stored in Lua variables. A userdata value represents a block of raw memory. There are two kinds of userdata:userdata
, which is an object with a block of memory managed by Lua, andlightuserdata
, which is simply a C pointer value.See also
Lua’s manual on value types.
-
class lightuserdata¶
The type
lightuserdata
is a sub-type ofuserdata
that only allows values with light userdata representation.
-
class thread¶
The type
thread
represents independent threads of execution and it is used to implement coroutines. Lua threads are not related to operating-system threads. Lua supports coroutines on all systems, even those that do not support threads natively.
-
class table<K, V>¶
The type table implements associative arrays, that is, arrays that can have as indices not only numbers, but any Lua value except
nil
andNaN
. (Not a Number is a special floating-point value used by the IEEE 754 standard to represent undefined or unrepresentable numerical results, such as0/0
.)While lua allows mixing types of keys and values in a table, EmmyLua has an option to specify their exact types. Simply using type
table
creates a heterogeneous table (equivalent totable<unknown, unknown>
), while explicitly providing key and value types creates a homogeneous table:--- @type table local tableWithArbitraryData = {} --- @type table<string, integer> local tableWithStringKeysAndIntValues = {}
You can also specify the exact shape of a table by using a table literal:
--- @type { username: string, age: integer } local User = { ... }
See also
Lua’s manual on value types.
-
class any¶
The type
any
is compatible with any other type. That is, all types can be converted to and fromany
.This type is a way to bypass type checking system and explicitly tell EmmyLua that you know what you’re doing.
-
class unknown¶
The type
unknown
is similar toany
, but signifies a different intent.While
any
is a way to say “I know what I’m doing”,unknown
is a way to say “better check this value before using it”.
-
class self¶
A special type used with class methods. It can be thought of as a generic parameter that matches type of the function’s implicit argument
self
. That is, when a function is called via colon notation (i.e.table:method()
),self
is replaced with the type of expression before the colon.This is especially handy when dealing with inheritance. Consider the following example:
--- @class Base local Base = {} --- @return self function Base:new() return setmetatable({}, { __index=self }) end --- @class Child: Base local Child = setmetatable({}, { __index=Base }) local child = Child:new()
Here, EmmyLua infers type of
child
to beChild
, even thoughnew
was defined in its base class. This is becausenew
usesself
as its return type.
Metaprogramming library¶
-
alias std.NotNull<T> =
sub
<T
,nil
>¶ A type for
assert
function. Given a nullable typeT
expands to a non-nullable version ofT
.For example, if
T
isstring?
, thenstd.NotNull<T>
will bestring
.
-
alias std.Unpack<T, Start, End> =
unknown
¶ A type for
table.unpack
function. Given a typeT
and optional literal typesStart
andEnd
, expands to the type of expressiontable.unpack(t, start, end)
.Example:
--- @generic T --- @param list T --- @return std.Unpack<T> function customUnpack(list) end local a, b, c = customUnpack({1, 2, 3})
Here,
a
,b
andc
will be inferred as integers.
-
alias std.RawGet<T, K> =
unknown
¶ A type for
rawget
function. Given a typeT
and a literal typeK
, expands to the type of expressionrawget(t, k)
.Example:
--- @class Example --- @field value integer --- @type std.RawGet<Example, "value"> local value
Here,
std.RawGet<Example, "value">
will be expanded tointeger
.
-
alias std.ConstTpl<T> =
unknown
¶ A wrapper for matching literal types in generics.
By default, generics variables that match literal values decay to values’ base types:
--- @generic T --- @param x T --- @return T local function id(x) return x end local original --- @type "literal" local value = id(original)
Here, type of
value
will be inferred asstring
even thoughoriginal
’s type was"literal"
.We can prevent this behavior by wrapping generic pattern for
T
intostd.ConstTpl<T>
:--- @generic T --- @param x std.ConstTpl<T> --- @return T local function id(x) return x end local original --- @type "literal" local value = id(original)
Here, type of
value
will be inferred as"literal"
.