Skip to main content
skill CX Codex

roblox-luau-types — Claude Code skill: Luau types in Roblox

A skill for Luau type annotations: generics, unions, narrowing, strict mode, module type exports. Useful when migrating to --!strict.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add TabooHarmony/roblox-brain --skill roblox-luau-types -a claude-code
Open on GitHub

What roblox-luau-types does

The skill gives your agent a reference for the Luau type system. It covers when to pick --!strict, --!nonstrict or --!nocheck, how the new type solver works, and why keyof, rawkeyof, setmetatable<T, M>, type function and read members fail without it. Errors in those spots usually mean the wrong solver, not wrong syntax.

The approach is infer first, annotate boundaries: params, returns, exports. Annotating every local is a waste. There's a section on sealed and unsealed tables too. An unannotated local table stays open to new fields until you annotate it, return it from a function, or its scope exits. Build the table fully before annotating.

Also inside: unions and tagged unions narrowed on kind, narrowing through typeof, IsA and assertions, optional keys as { [K]: V? }, literal unions for closed vocabularies, generics like function first<T>(list: {T}): T?, and export type Foo at module boundaries. On casts, the guidance is blunt: :: narrows overly generic inference, it does not hide errors. One limit matters — annotations contract with the compiler, not runtime data. Remotes, DataStores, HttpService and attributes still need checks.

What it helps with

  • annotate a module before migrating it to --!strict
  • work out why keyof or a type function fails the type check
  • build a tagged union and narrow it on the kind field
  • expose types from a module with export type for other files
  • seal a table against new fields with an annotation

Example prompts for the agent

  • add type annotations to this module and turn on --!strict
  • why does keyof fail the type check here — look at the solver
  • make a tagged union for loading states and narrow it on kind

How to install roblox-luau-types

1Skills CLI (Vercel)

npx skills add TabooHarmony/roblox-brain --skill roblox-luau-types -a claude-code

2Manually: put the files in place

~/.claude/skills/roblox-luau-types/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/roblox-luau-types/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about roblox-luau-types

How do I install roblox-luau-types in Claude?

Run npx skills add TabooHarmony/roblox-brain --skill roblox-luau-types -a claude-code. The skill lands in ~/.claude/skills/roblox-luau-types/SKILL.md.

What does roblox-luau-types do?

It hands your agent a Luau type reference: strictness modes, inference, narrowing, unions, generics, type exports and typed metatables. The agent leans on it while fixing annotations and reading type checker errors.

Do I need the new Luau type solver?

For keyof, rawkeyof, setmetatable<T, M>, type function and read members, yes. It is on by default for nocheck and nonstrict projects; strict projects need Workspace.UseNewLuauTypeSolver = Enabled.

Source text

SKILL.md · MIT
---
name: roblox-luau-types
description: "Use when adding or fixing Luau type annotations: generics, unions, narrowing, strict mode, sealed tables, module type exports, typed metatables."
when_to_use: "Also for type checker errors and warnings, --!strict migration, luau-lsp diagnostics, and reviewing typed APIs."
last_reviewed: 2026-10-14
sources:
  - https://raw.githubusercontent.com/Roblox/creator-docs/main/content/en-us/luau/type-checking.md
  - https://luau.org/types/type-functions/
  - https://luau.org/types/tables
  - https://raw.githubusercontent.com/Kampfkarren/kampfkarren-luau-guidelines/main/README.md
---

# Luau Type System

## When to Load

Load for Luau annotations, inference, narrowing, strictness, exports, and solver features. Syntax: `roblox-luau-core`; lifecycle/scheduling: `roblox-luau-patterns`.

## Quick Reference

**Strictness:** `--!strict` for maintained code, `--!nonstrict` while transitioning, `--!nocheck` only for legacy or generated code. Directives and project settings select the mode; never assume one global default.

**New solver gate:** `keyof`, `rawkeyof`, `setmetatable<T, M>`, `type function`s, and `read` members need the new type solver. On by default for `nocheck`/`nonstrict` projects; strict projects need `Workspace.UseNewLuauTypeSolver = Enabled` (Scripting). Errors here usually mean wrong solver, not wrong syntax.

**Inference philosophy:** Infer first; annotate boundaries (params, returns, exports). Don't annotate every local.

**Sealed vs unsealed tables:** An unannotated local table stays open to new fields until annotated, returned from a function, or its scope exits; annotation seals it. Build tables fully before annotating; passing a table to a typed function does not seal it.

**Unions:** `local id: string | number` is a union; prefer tagged unions (`type State<T> = {kind:"loading"} | {kind:"ready", value:T}`) and discriminate on `kind` to narrow.

**Narrowing:** `typeof`, `IsA`, assertions, and tagged discriminants refine types; examples in full.md.

**Missing keys:** use `{ [K]: V? }` when lookups may miss; narrow before use.

**Closed vocabularies:** prefer literal unions; `never` checks can flag missing branches. Keep requires statically resolvable. Practitioner guidance: full.md.

**Generics:** Use when input→output type matters: `function first<T>(list: {T}): T?`, or `type Result<T> = {success: boolean, value: T?}`. Never replace with `any`.

**Type exports:** `export type Foo = {...}` at module boundaries; consumers use `Types.Foo`.

**Object typing:** `typeof(setmetatable({} :: CounterData, Counter))` types precise self; the new solver adds `setmetatable<T, M>` directly.

**Casts (::):** For narrowing overly generic inference, never for hiding errors.

**Trust boundaries:** Annotations contract with the compiler, not runtime data. Remotes, DataStores, HttpService, and attributes still need checks; inside a trusted boundary, let types carry the load.

**Review:** no hidden `any`, premature sealing, unchecked casts, or solver-blind rewrites.

> Full reference: see `references/full.md`

© TabooHarmony · MIT · TabooHarmony/roblox-brain

Similar skills

All skills for Programming languages →

From the same set28

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor