Roblox Luau Types
Use for Luau annotations, generics, unions, narrowing, strictness, sealed tables, module type exports, or typed metatables.
- Skill ID
- tabooharmony/roblox-brain/roblox-luau-types
- Publisher
- tabooharmony
- Repository
- roblox-brain
- Installs
- 0
- Files
- 2
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
tabooharmony/roblox-brain/roblox-luau-typesInstalls these files- SKILL.md
- references/full.md
What this skill tells the agent
Luau Type System
When to Load
Load for Luau type system work: annotations, generics, union types, type narrowing, sealed/unsealed tables, strictness modes (--!strict vs --!nonstrict), module type exports, and metatable-backed object typing. For syntax questions, use roblox-luau-core. For OOP/async/modules, use roblox-luau-patterns.
Quick Reference
Strictness: Use --!strict for maintained code, --!nonstrict while transitioning, and --!nocheck only for legacy/generated code. Project settings and directives select the mode; do not assume one global default.
Inference philosophy: Infer first, annotate boundaries (params, returns, exports). Don't annotate every local. Noise hides signal.
Sealed vs unsealed tables:
local t = {} -- unsealed: can add fields
t.x = 1 -- OK
local t: {x: number} = {x=1} -- sealed: no new fields
t.y = 2 -- ERRORBuild tables fully before annotating. Passing/returning seals them.
Unions & tagged unions:
local id: string | number = "abc"
type State<T> = {kind:"loading"} | {kind:"ready", value:T} | {kind:"fail", msg:string}
-- Discriminate: if state.kind == "ready" then state.value is narrowedNarrowing:
if typeof(value) == "string" then
print(string.upper(value)) -- primitive narrowing
end
if instance:IsA("BasePart") then
print(instance.Position) -- Instance narrowing
end
assert(optionalValue, "missing") -- non-nil narrowingGenerics: Use when input→output type matters. function first<T>(list: {T}): T?. Generic aliases: type Result<T> = {success: boolean, value: T?}. Never replace with any.
Type exports: export type Foo = {...} at module boundary. Consumers use require + Types.Foo.
Object typing: export type Counter = typeof(setmetatable({} :: CounterData, Counter)) for precise self.
Casts (::): Precision tool to narrow overly generic inference, never to hide errors.
Write types you can trust: annotations are contracts for the compiler, not proof of runtime validity. Trust boundaries (remotes, DataStores, HttpService, attributes) still get runtime checks even when everything is annotated; inside a trusted boundary, let types carry the load instead of re-checking every call.
Key mistakes: Unsealed any propagation in nonstrict, sealing tables too early, unions without discriminants, annotating every local.
Full reference: see references/full.mdMore from tabooharmony
Use this skill in a project
Open any RiverX project, search the Skills panel for tabooharmony/roblox-brain/roblox-luau-types, and install it in one click.
