{"id":"tpc9000/typeguard","name":"typeguard","scope":"tpc9000","platform":"roblox","description":"Mirrored from the Wally registry.","version":"5.0.0","latest":"5.0.0","versions":["0.1.0","1.0.0","1.1.0","1.2.0","2.0.0","2.1.0","2.2.0","2.2.1","2.3.0","2.4.0","2.4.2","3.0.0","3.0.1","3.1.0","3.2.0","3.3.0","3.3.1","4.0.0","5.0.0","6.0.0-alpha.1","6.0.0-alpha.2","6.0.0-alpha.3","6.0.0-alpha.5","6.0.0-alpha.6"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"70280a16919ec58e2dc48e0f2b777aa369db70e240225d86bfa0eb2ce64a5646","likes":0,"downloads":0,"install":"forest install tpc9000/typeguard","url":"https://forest.dev/p/roblox/tpc9000/typeguard","files":"https://api.forest.dev/ai/package/roblox/tpc9000/typeguard/files","readme":"# TypeGuard\r\n\r\nA runtime assertion & type-checking library. This aims to replace most assertions and manual type checks with a consistent, callable pattern.\r\n\r\n## Usage Examples\r\n\r\n### 1: standard params, simple\r\n```lua\r\nlocal AssertRandomParams = TypeGuard.Params(\r\n    TypeGuard.String(),\r\n    TypeGuard.Boolean(),\r\n    TypeGuard.Any()\r\n)\r\n\r\nlocal function Test(P: string, Q: boolean, R: any)\r\n    AssertRandomParams(P, Q, R)\r\n    -- ...\r\nend\r\n```\r\n\r\n### 2: each provided arg must be an integer\r\n```lua\r\nlocal AssertSumInts = TypeGuard.Variadic(TypeGuard.Number():Integer())\r\n\r\nlocal function SumInts(...: number)\r\n    AssertSumInts(...)\r\n    -- ...\r\nend\r\n```\r\n\r\n### 3: TypeChecker disjunction with a custom failure message\r\n```lua\r\nlocal AssertStringOrNumberOrBoolean = TypeGuard.Params(\r\n    TypeGuard.String()\r\n        :Or(TypeGuard.Number())\r\n        :Or(TypeGuard.Boolean())\r\n        :FailMessage(\"expected a string, number, or boolean\")\r\n)\r\n\r\nlocal function Test(Input: string | number | boolean)\r\n    AssertStringOrNumberOrBoolean(Input)\r\n    -- ...\r\nend\r\n```\r\n\r\n### 4: TypeChecker conjunction\r\n```lua\r\nlocal AssertStructureCombined = TypeGuard.Params(\r\n    -- 'And' only really makes sense on non-strict structural checks for arrays, objects, and Instances\r\n    TypeGuard.Object({\r\n        X = TypeGuard.Number();\r\n    }):And(\r\n        TypeGuard.Object({\r\n            Y = TypeGuard.Number();\r\n        })\r\n    ):And(\r\n        TypeGuard.Object({\r\n            Z = TypeGuard.Number();\r\n        })\r\n    )\r\n)\r\n\r\nlocal function Test(Input: {X: number} & {Y: number} & {Z: number})\r\n    AssertStructureCombined(Input)\r\n    -- ...\r\nend\r\n```\r\n\r\n### 5: context passing (functional constraint): assert that the provided Model a descendant of Workspace\r\n```lua\r\nlocal AssertTestContext = TypeGuard.ParamsWithContext(\r\n    TypeGuard.Instance(\"Model\"):IsDescendantOf(function(Context)\r\n        return Context.Reference\r\n    end)\r\n)\r\n\r\nlocal function Test(Root: Model)\r\n    AssertTestContext({Reference = workspace}, Root)\r\n    -- ...\r\nend\r\n```\r\n\r\n### 6: Optional params\r\n```lua\r\nlocal AssertTestOptional = TypeGuard.Params(\r\n    TypeGuard.String(),\r\n    TypeGuard.Vector3():Optional()\r\n)\r\n\r\nlocal function Test(X: string, Y: Vector3?)\r\n    AssertTestOptional(X, Y)\r\n    -- ...\r\nend\r\n```\r\n\r\n### 7: validating tables passed to RemoteEvents recursively, with various principles combined\r\n```lua\r\nlocal AssertValidTest = TypeGuard.Params(\r\n    TypeGuard.Instance(\"Player\"):IsDescendantOf(game:GetService(\"Players\")),\r\n\r\n    TypeGuard.Object({\r\n        P = TypeGuard.Number():IsAValueIn({1, 2, 3, 4, 5});\r\n        Q = TypeGuard.Number():Integer():RangeInclusive(-100, 100);\r\n        R = TypeGuard.Array(TypeGuard.String()):MaxLength(100);\r\n\r\n        S = TypeGuard.Object({\r\n            Key1 = TypeGuard.String():Optional();\r\n            Key2 = TypeGuard.Enum(Enum.Material);\r\n        }):Strict();\r\n\r\n        T = TypeGuard.Number():IsInfinite():Negate():IsClose(123, 0.5):Negate(); -- \"number should not be infinite and should not be close to 123\"\r\n    }):Strict()\r\n)\r\n\r\nSomeRemoteEvent.OnServerEvent:Connect(function(Player: Player, TestData: {P: number, Q: number, R: {string}, S: {Key1: string?, Key2: Enum.Material?}, T: number})\r\n    AssertValidTest(Player, TestData)\r\n    -- ...\r\nend)\r\n```\r\n\r\n### 8: Instance filtering via wrapping check into predicate: find all alive Humanoids whose characters are not tagged with \"Ignore\"\r\n```lua\r\nlocal IsHumanoidAlive = TypeGuard.Instance(\"Model\", {\r\n    Humanoid = TypeGuard.Instance(\"Humanoid\", { -- Scans children recursively\r\n        Health = TypeGuard.Number():GreaterThan(0); -- Scans properties\r\n    });\r\n}):HasTag(\"Ignore\"):Negate():WrapCheck()\r\n\r\nlocal AliveHumanoids = SomeTableLibrary.Filter(Workspace:GetChildren(), IsHumanoidAlive)\r\n```\r\n\r\n### 9: constructing a checker from a template object\r\n```lua\r\nlocal Tree = Instance.new(\"Model\")\r\n    local Part1 = Instance.new(\"Part\")\r\n    Part1.Name = \"Part1\"\r\n    Part1.Parent = Tree\r\n    local Part2 = Instance.new(\"Part\")\r\n    Part2.Name = \"Part2\"\r\n    Part2.Parent = Tree\r\n\r\nlocal Checker = TypeGuard.FromTemplate({\r\n    X = 1;\r\n    Y = 2;\r\n    Z = 3;\r\n\r\n    P = {\r\n        Q = Vector3.new();\r\n        R = Tree;\r\n    };\r\n\r\n    Arr = {1, 2, \"X\", \"Y\"}; -- Accepts strings or numbers\r\n})\r\n-- ^ created a deep Object TypeChecker\r\n```\r\n\r\n\r\n## Best Practices\r\nAvoid construction or copying of TypeCheckers for performance reasons. TypeCheckers are copied with each added constraint or change, and are supposed to exist outside of frequently called functions. If you need to pass dynamic data down, use context & functional constraints.","readmeTruncated":false}