mcpField
L
luau-types

luau-types

github.com/luumenlabs開発13173 回インストール22 週間前に更新
リポジトリ

luau-types について

luau-typesは、Luauの型システムを中心とする作業向けのスキルです。Luauコードの作成やレビューに使われ、型推論、ジェネリクス、ユニオン、テーブル、モジュールAPIを扱います。実行時最適化やRobloxのアーキテクチャは対象外です。

主な機能

  1. 01ファイルの型チェックモード選択
  2. 02変数、関数、テーブルの型付け
  3. 03推論を保つAPI設計
  4. 04ジェネリクスとユニオンのモデル化
  5. 05モジュールとメタテーブルの型付け

活用シーン

  1. 01Luauファイルのstrictモード選択
  2. 02安定した公開モジュール型の定義
  3. 03ジェネリクスによる入出力関係の保持
  4. 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.md
generics.md
object-oriented-typing.md
refinements.md
roblox-types-in-luau.md
type-functions.md
type-system-overview.md
unions-and-intersections.md

詳細

luau-types

使用するタイミング

タスクの主な内容が Luau の型システムに関する場合に、このスキルを使用します。

  • --!strict、--!nonstrict、その他のファイルの型チェックモードから選択する。
  • 変数、関数、テーブル、モジュールの型注釈を追加または修正する。
  • any に帰着せず、型推論を維持する API を設計する。
  • ジェネリック、ユニオン、インターセクション、オプショナル、タグ付きユニオンを使ってデータをモデル化する。
  • オブジェクトのようなテーブル、メタテーブルを使ったモジュール、エクスポートするモジュールの公開インターフェースに型を付ける。
  • 型関数やその他の高度な型レベルのユーティリティを記述またはレビューする。
  • Roblox のクラス、データ型、列挙型、IsA に関する知識を、静的な型付けの改善にのみ使用する。

タスクの主な内容が次の項目に関する場合は、このスキルを使用しないでください。

  • 型付けの問題以外の、Luau の一般的な構文、制御フロー、メタテーブル、標準ライブラリの使用方法。
  • ランタイムのパフォーマンス、プロファイリング、実行頻度の高い箇所の最適化、メモリ割り当ての方針。
  • Roblox のネットワーク通信、レプリケーション、データストレージ、クラウド API、ゲームプレイのアーキテクチャ。

判断ルール

  • 主な質問が「この型はどうあるべきか?」または「このコードの型チェックを長期的にどう維持すべきか?」である場合、このスキルを使用します。
  • タスクが移行中のコードやレガシーコードを明示的に対象としていない限り、新規コードまたは積極的に保守されているコードでは --!strict を推奨します。
  • 推論された形状が正確で読みやすいまま保たれる場合は、注釈を多用する設計よりも、型推論を維持する設計を優先します。
  • 利用側で安定した契約を共有する必要がある場合は、モジュールの境界で明示的にエクスポートするエイリアスを優先します。
  • 入力と出力の関係が重要な場合はジェネリックを使用し、その関係を any に置き換えないでください。
  • 値が複数の構造化されたケースのいずれかになり得る場合は、タグ付きユニオンと型の絞り込みを使用します。
  • タスクが純粋な言語構文の話に移った場合は、luau-core に引き継ぎます。
  • タスクが最適化やランタイムコストのトレードオフの話に移った場合は、luau-performance に引き継ぎます。
  • タスクに型名や型の絞り込みを超えた Roblox ランタイムのアーキテクチャが必要な場合は、適切な roblox/* スキルを使用します。
  • 判断に迷った場合は、型付けの正確性、保守性、またはアナライザーの動作の改善に直接必要のない内容を除外します。

指示

  1. まず、ファイルモードの要件を特定します。
    • 強力な推論と早期のエラー検出には --!strict を使用します。
    • 未解決の値がノイズになる移行中のコードには --!nonstrict を使用します。
    • 分析の無効化がタスクで明示的に求められている場合に限り、--!nocheck を使用します。
  2. あらゆる箇所に注釈を追加する前に、有用な推論を維持します。意図を明確にする場合、モジュールの契約を安定させる場合、self を制約する場合、または望ましくない any への型の拡大を防ぐ場合に注釈を追加します。
  3. 共有する形状には、具体的なエイリアスを優先します。
    • 構造化データにはレコードを使用します。
    • 辞書にはインデクサーを使用します。
    • 配列には {T} を使用します。
    • モジュール間で使う契約には、エクスポートされたエイリアスを使用します。
  4. オプショナル型、ユニオン型、インターセクション型を意図的に使います。
    • T | nil には T? を使用します。
    • 状態機械や結果のような値にはタグ付きユニオンを使用します。
    • 互換性のあるテーブル機能や関数シグネチャの組み合わせにはインターセクションを使用します。
  5. :: によるキャストは、回避策ではなく精度を高める手段として扱います。過度に汎用的な推論を絞り込むために使用し、無関係な型のエラーを隠すためには使用しません。
  6. ジェネリックは、型同士の関係を表すように設計します。
    • 変換処理を通じて要素型を維持します。
    • コンテナーを通じてキーと値の関係を維持します。
    • 型パラメーターで意図を表現できる場合に、any を既定にしないようにします。
  7. Luau の解析方法に応じてテーブルをモデル化します。
    • 非シールテーブルには、ローカルでフィールドを追加できます。
    • 注釈付きのテーブルや返されるテーブルはシールされます。
    • シールされたレコードには幅部分型付けが適用されます。
  8. オブジェクトのようなモジュールでは、インスタンスデータとクラスの振る舞いを分離し、setmetatable からインスタンス型を導出します。また、メソッドで共有のクラス型が必要な場合は、self に明示的な注釈を付けます。
  9. モジュールの API サーフェスを型安全に保ちます。
    • 利用側に公開するデータには、名前付きエイリアスをエクスポートします。
    • 実装の詳細は内部に留めます。
    • 呼び出し側の型を適切に推論できるシグネチャを選びます。
  10. Roblox の型知識は、Instance、Part、Enum.Material、データ型、IsA による絞り込みなど、注釈と型の絞り込みにのみ使用します。

参照資料の使用

  • ファイルモード、構造的型付け、注釈、キャスト、モジュール境界に関するガイダンスについては、references/type-system-overview.md を開いてください。
  • 組み込み型、any や unknown などの特殊な型、関数シグネチャ、テーブルの状態、インデクサーについては、references/basic-types-and-table-typing.md を開いてください。
  • ジェネリックエイリアス、ジェネリック関数、エイリアスの既定値、推論を維持するコンテナーパターンについては、references/generics.md を開いてください。
  • 結果の形状、タグ付きユニオン、識別子、安全なインターセクションの使用については、references/unions-and-intersections.md を開いてください。
  • 真偽値によるチェック、type(...) ガード、等価性による絞り込み、複合条件、assert による絞り込みについては、references/refinements.md を開いてください。
  • メタテーブルを使ったクラスの型付け、self の注釈、コンストラクターの戻り値の型、エクスポートされたインスタンスエイリアスについては、references/object-oriented-typing.md を開いてください。
  • 解析時の型計算、利用可能なライブラリ、高度な型レベル変換が妥当な場合については、references/type-functions.md を開いてください。
  • Roblox のクラス、データ型、列挙型、コンストラクター、サービス、IsA の型付け動作については、references/roblox-types-in-luau.md を開いてください。
  • 依頼内容が明らかにスキルの範囲をまたぐ場合を除き、ほかのスキル参照資料は開かないでください。

チェックリスト

  • 選択した型チェックモードが、ファイルの保守目的に合っています。
  • 再利用が重要な箇所では、公開モジュールの契約が明示されています。
  • 型推論の精度が保たれる場合は、型推論を活用しています。
  • 意図的に型チェックを無効にする場合を除き、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

コメント