Part of Learn Lua with NeoVim

Learn Lua in Neovim: Variables and Types — local, type() & Nil | Episode 2

Sandy LaneSandy Lane

Video: Learn Lua in Neovim: Variables and Types — local, type() & Nil | Episode 2 by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

Lua Variables and Types: local, type(), and Nil

local name = "Alice" to declare. Four basic types — string, number, boolean, nil. type(x) to inspect. The .. operator for string concatenation.

Lua has a compact type system: four basic value types you'll use every day, plus tables (next week) and functions (week three). Today we cover the four basic types and how to declare variables.

The four basic types

-- Strings hold text
local name = "Alice"
print(name)
print(type(name))

-- Numbers hold integers and decimals
local age = 25
print(age)
print(type(age))

-- Booleans hold true or false
local is_student = true
print(is_student)
print(type(is_student))

-- Nil means "no value"
local nickname = nil
print(nickname)
print(type(nickname))

Run it and you see:

Alice
string
25
number
true
boolean
nil
nil

type(value) returns a string describing the value's type. It's the canonical way to check what kind of thing you're holding.

Always say local

local name = "Alice"     -- local: only visible in this scope
name = "Alice"           -- global: visible everywhere

In Lua, undeclared variables are global by default. That's the opposite of most languages, and it's a footgun — typos silently create new global variables.

local count = 0
cuont = count + 1   -- typo creates a global, count stays 0

Always use local unless you specifically need a global. Episode 14 covers scope in detail; for now, treat local as a habit.

Numbers: one type for both

Lua's number type covers both integers and decimals (called "floats" in other languages). Lua 5.3+ distinguishes them internally for performance, but you mostly don't notice.

local count = 5         -- integer
local price = 12.99     -- float
local mixed = count + price  -- 17.99 (float)

Mixing them works seamlessly. The result is a float if either operand is a float.

Strings: double or single quotes

local first = "Alice"
local last = 'Smith'

Both are valid strings. There's no difference in semantics — just pick whichever doesn't clash with the content.

For multi-line strings, use [[ ... ]] (covered in episode 4). For embedding quotes, escape with \:

local message = "She said \"hi\""

String concatenation with ..

print(name .. " is " .. age .. " years old")

The .. operator joins two strings. Lua auto-converts numbers to strings when concatenating, so "is " .. 25 works without explicit casting.

Many languages use + for both addition and concatenation. Lua keeps them separate — + is always arithmetic, .. is always concatenation. No ambiguity.

Nil: the absence of a value

local nickname = nil
print(nickname)        -- prints: nil
print(type(nickname))  -- prints: nil

nil is Lua's "no value" marker. Reading a variable that was never assigned returns nil:

print(undefined_var)   -- prints: nil (no error)

That's very permissive — most languages would crash. Lua just hands back nil. The flip side: typos silently produce nil instead of an error. Watch for it.

The summary line

print("--- Summary ---")
print(name .. " is " .. age .. " years old")

Output:

--- Summary ---
Alice is 25 years old

The .. chain converts age (a number) to a string automatically. For controlled formatting (decimal places, padding, etc.), reach for string.format():

print(string.format("%s is %d years old", name, age))

%s for strings, %d for integers, %f for floats. Same as C's printf.

What other types exist?

The list of Lua types in full:

  • nil
  • boolean
  • number
  • string
  • function (covered in episode 12)
  • table (covered in episode 17)
  • userdata and thread (advanced; rarely used directly)

function and table are the tools that make Lua programs interesting. We get to them as soon as we have control flow under our belts.

Common stumbles

Forgot local. name = "Alice" creates a global that's visible everywhere. Subtle bug source. Always local name = "Alice".

Concatenating with +. name + " " + last is an error — + is arithmetic, not concatenation. Use ...

Comparing types as if they were enums. if type(x) == "number" — yes, type() returns a string, so the comparison is a string comparison.

Treating nil as falsy in arithmetic. nil + 5 errors. Only the control-flow operators (if, and, or) treat nil as falsy. Math operations require numbers.

What's next

Episode 3: numbers and arithmetic. + - * /, plus floor division //, modulo %, exponent ^, and a small receipt calculator.

Recap

Four basic types: string, number, boolean, nil. local x = value to declare. type(value) to inspect. .. for string concatenation (numbers auto-convert). nil is Lua's "no value" — silently returned for undeclared variables.

Next episode: numbers and arithmetic.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.