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 optionalYou'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")
endOptional means "may be absent". It does not mean "any type". If email exists, it must still be a string.
Challenge
EasyPrint contacts whose email may be missing.
- Write
type User = {name: string, email: string?}, thenlocal mia: User = {name = "Mia", email = "mia@coddy.tech"}andlocal leo: User = {name = "Leo"}. - Write
local function printContact(user: User)printing`{user.name}: {user.email}`, or`{user.name}: no email`without one. - Call it for
mia, thenleo.
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
1Getting Started with Luau
What Is Luau?Why Use Luau?Your First Luau CodeType Checking & Error ModesRecap: Introduction to Luau4Working with Functions
Typing Params & Return ValuesTyping Anonymous FunctionsFunctions Returning NothingOptional ParametersDefault Parameter ValuesDefaults for BooleansVariadic FunctionsDefining Function TypesRecap: Typed Functions2Core Types
Number, String and BooleanThe 'any' Type: Escape HatchThe 'unknown' TypeNil & Optional TypesType Inference in ActionExplicit Type AnnotationsRecap: Core Types Practice5Aliases, Unions, Intersections
Type Aliases for PrimitivesUnion TypesWorking with Union TypesLiteral TypesIntersection TypesCombining Type AliasesRecap: Advanced Type Combos3Typed Tables: Arrays & Maps
Typed ArraysAdding and Reading ElementsWhat is a Map Type?Declaring and Accessing MapsIterating TablesMixed-Shape TablesReading a GridBuilding a Gridtable.unpackRecap: Arrays and MapsPractice on your own: Online Luau compiler