Menu
CoddyTech

Optional Properties

Part of the Introduction To Luau section of Coddy's Lua journey. Lesson 41 of 80.

Not every field is always present. In Lua, a missing table field simply reads as nil, which is flexible, but also how bugs like attempt to concatenate a nil value sneak in.

Luau lets a shape say this explicitly: add ? after a field's type to mark it optional:

type User = {
    name: string,   -- required
    email: string?, -- optional: string or nil
}

local alice: User = {name = "Alice", email = "alice@luau.dev"}
local bob: User = {name = "Bob"} -- ✓ fine, email is optional

You've met this before with variables: string? is shorthand for string | nil. The same idea now applies to individual fields of a shape.

Because an optional field might be nil, you must check before using it. The classic Lua pattern works, and in strict mode the checker narrows the type inside the branch:

if bob.email then
    print(`email: {bob.email}`) -- here email is a string
else
    print("no email on file")
end

Optional means "may be absent". It does not mean "any type". If email exists, it must still be a string.

challenge icon

Challenge

Easy

Print contacts whose email may be missing.

  1. Write type User = {name: string, email: string?}, then local mia: User = {name = "Mia", email = "mia@coddy.tech"} and local leo: User = {name = "Leo"}.
  2. Write local function printContact(user: User) printing `{user.name}: {user.email}`, or `{user.name}: no email` without one.
  3. Call it for mia, then leo.

Press Run Code: the output shows Mia: mia@coddy.tech and Leo: no email.

Try it yourself

-- 1) type User with an optional email, then mia and leo
-- 2) printContact(user: User) with a check on the email
-- 3) call it for mia, then leo

All lessons in Introduction To Luau

Practice on your own: Online Luau compiler