关于 luau-types
luau-types 是面向 Luau 类型系统任务的 Skill,供编写或审查 Luau 代码的开发者使用。它聚焦类型推断、泛型、联合类型、表与模块 API,并避免偏离到运行时优化或 Roblox 架构。
主要功能
- 01选择文件类型检查模式
- 02为变量、函数和表添加类型
- 03设计保留推断的 API
- 04建模泛型与联合类型
- 05处理模块与元表类型
适用场景
- 01为 Luau 文件选择 strict 模式
- 02为模块定义稳定的导出类型
- 03用泛型保留输入输出关系
- 04为状态模型设计带标签联合类型
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ luumenlabs/ luau-skills --skill luau-types安装后在 Claude Code 中输入/luau-types确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/basic-types-and-table-typing.mdgenerics.mdobject-oriented-typing.mdrefinements.mdroblox-types-in-luau.mdtype-functions.mdtype-system-overview.mdunions-and-intersections.md详细介绍
luau-types
适用场景
当任务主要涉及 Luau 的类型系统时,请使用此技能:
- 在
--!strict、--!nonstrict和其他文件类型检查模式之间进行选择。 - 为变量、函数、表和模块添加或修正类型注解。
- 设计能够保留类型推断,而不会退化为
any的 API。 - 使用泛型、联合类型、交集类型、可选类型和带标签的联合类型来建模数据。
- 为类对象表、由元表支持的模块以及导出的模块接口添加类型。
- 编写或审查类型函数和其他高级类型级实用工具。
- 仅使用 Roblox 类、数据类型、枚举或
IsA知识来改进静态类型。
当任务主要涉及以下内容时,请勿使用此技能:
- 与类型无关的一般 Luau 语法、控制流、元表或标准库用法。
- 运行时性能、性能分析、热点调优或分配策略。
- Roblox 网络、复制、数据存储、云 API 或游戏架构。
决策规则
- 如果核心问题是“这个类型应该是什么?”或“这段代码应如何随着时间推移通过类型检查?”,请使用此技能。
- 对于新代码或积极维护的代码,优先采用
--!strict指南,除非任务明确针对过渡期或旧版代码。 - 如果推断出的结构仍然精确且易读,优先采用保留类型推断的设计,而不是大量添加类型注解。
- 如果模块的使用者需要共享稳定的契约,优先在模块边界显式导出类型别名。
- 当输入与输出之间的关系很重要时,请使用泛型;不要用
any取代这种关系。 - 当一个值可能属于多个结构化情形之一时,请使用带标签的联合类型和类型细化。
- 如果任务转向纯语言语法,请转交给
luau-core。 - 如果任务转向优化或运行时成本权衡,请转交给
luau-performance。 - 如果任务需要的 Roblox 运行时架构超出类型名称和类型细化的范围,请改用适当的
roblox/*技能。 - 如有疑问,请排除所有非直接用于提升类型正确性、可维护性或分析器行为的内容。
Instructions
- 首先确定文件模式要求:
--!strict用于强化类型推断并及早发现错误。--!nonstrict用于过渡性代码,避免未解析的值造成过多干扰。- 仅在任务明确要求禁用分析时使用
--!nocheck。
- 在到处添加注解之前,先保留有用的类型推断。在注解能明确意图、稳定模块契约、约束
self或避免不必要地扩大为any时,再添加注解。 - 对共享的数据形状,优先使用具体别名:
- 结构化数据使用记录。
- 字典使用索引器。
- 数组使用
{T}。 - 面向模块的契约使用导出的别名。
- 有意识地使用可选类型、联合类型和交集类型:
- 用
T?表示T | nil。 - 对状态机或类似结果的值使用带标签的联合类型。
- 使用交集类型组合兼容的表能力或函数签名。
- 用
- 将
::强制转换视为精确调整类型的工具,而非绕过检查的手段。用它收窄过于宽泛的推断,不要用它掩盖无关类型错误。 - 围绕类型之间的关系设计泛型:
- 在转换过程中保留元素类型。
- 在容器中保留键和值之间的关系。
- 当类型参数能够表达意图时,避免默认使用
any。
- 根据 Luau 的分析方式对表建模:
- 未封闭的表可以在本地累积字段。
- 带注解或作为返回值的表会被封闭。
- 封闭记录支持宽度子类型。
- 对象式模块应将实例数据与类行为分开,从
setmetatable推导实例类型,并在方法需要共享类类型时显式注解self。 - 确保模块 API 表面具备类型安全性:
- 为面向使用者的数据导出具名别名。
- 将实现细节保留在模块内部。
- 选择能清晰推断调用者类型的签名。
- 仅将 Roblox 类型知识用于注解和类型细化,例如
Instance、Part、Enum.Material、数据类型以及由IsA驱动的收窄。
使用参考资料
- 打开
references/type-system-overview.md,了解文件模式、结构化类型、注解、强制转换和模块边界指导。 - 打开
references/basic-types-and-table-typing.md,了解内置类型、any和unknown等特殊类型、函数签名、表状态和索引器。 - 打开
references/generics.md,了解泛型别名、泛型函数、别名上的默认值,以及保留推断的容器模式。 - 打开
references/unions-and-intersections.md,了解结果形状、带标签的联合类型、判别字段和安全使用交集类型。 - 打开
references/refinements.md,了解真值检查、type(...)守卫、相等性收窄、复合条件和基于assert的收窄。 - 打开
references/object-oriented-typing.md,了解基于元表的类类型、self注解、构造函数返回类型和导出的实例别名。 - 打开
references/type-functions.md,了解分析时的类型计算、可用库,以及何时有必要进行高级类型级转换。 - 打开
references/roblox-types-in-luau.md,了解 Roblox 类、数据类型、枚举、构造函数、服务和IsA的类型行为。 - 除非请求明确涉及其他技能领域,否则不要打开其他技能参考资料。
检查清单
- 所选的类型检查模式与文件的维护目标相符。
- 在需要复用的地方明确声明公共模块契约。
- 在类型推断依然精确时保留推断。
- 避免使用
any,除非是有意选择不进行类型检查。 - 根据表的实际形状和封闭行为为其标注类型。
- 联合类型、交叉类型和可选类型应反映真实状态,而不是含糊的兜底类型。
- 泛型参数应编码调用方依赖的输入/输出关系。
- 当 Luau 无法安全推断共享类类型时,应明确标注方法的
self类型。 - 仅在有助于改进类型标注时使用 Roblox 类型,避免偏离主题而涉及无关的 Roblox 架构。
- 不包含通用语法教程、性能建议或网络/数据/云相关指导。
常见错误
- 在
--!nonstrict中不为变量添加类型标注,导致其意外变成any。 - 用
any或过于宽泛的联合类型取代有用的泛型关系。 - 过早通过类型标注封闭表,之后却期望能添加字段。
- 误以为使用
:定义的方法会自动在整个类中共享精确的self类型。 - 使用
::强制转换互不相关的类型,而不是修正根本的类型设计。 - 构建不带判别字段的联合类型,导致下游难以细化类型。
- 对
string & number这类互不兼容的基本类型使用交叉类型。 - 在仅涉及类型的任务中混入 Roblox 运行时架构指导。
示例
导出稳定的模块契约
--!strict
export type User = {
id: number,
name: string,
nickname: string?,
}
local M = {}
function M.makeUser(id: number, name: string): User
return {
id = id,
name = name,
nickname = nil,
}
end
return M
使用泛型函数保留关系
--!strict
local function first<T>(items: {T}): T?
return items[1]
end
local a = first({1, 2, 3}) -- number?
local b = first({"x", "y"}) -- string?
细化带标签的联合类型
--!strict
type Loading = { kind: "loading" }
type Ready<T> = { kind: "ready", value: T }
type Failed = { kind: "failed", message: string }
type State<T> = Loading | Ready<T> | Failed
local function readValue(state: State<number>): number?
if state.kind == "ready" then
return state.value
end
return nil
end
为带有显式 self 的类对象式模块标注类型
--!strict
local Counter = {}
Counter.__index = Counter
type CounterData = {
value: number,
}
export type Counter = typeof(setmetatable({} :: CounterData, Counter))
function Counter.new(initialValue: number): Counter
return setmetatable({
value = initialValue,
}, Counter)
end
function Counter.increment(self: Counter, amount: number): number
self.value += amount
return self.value
end
return Counter
评论
支持 Markdown