A runtime assertion, type-checking, and serialization library. This aims to replace most assertions and manual type checks with a consistent, callable pattern.
localAssertRandomParams=TypeGuard.Params(
TypeGuard.String(),
TypeGuard.Boolean(),
TypeGuard.Any()
)
localfunctionTest(P: string, Q: boolean, R: any)
AssertRandomParams(P, Q, R)
-- ...endlocalAssertSumInts=TypeGuard.Variadic(TypeGuard.Number():Integer())
localfunctionSumInts(...: number)
AssertSumInts(...)
-- ...endlocalAssertStringOrNumberOrBoolean=TypeGuard.Params(
TypeGuard.Or(
TypeGuard.String()
TypeGuard.Number()
TypeGuard.Boolean()
):FailMessage("expected a string, number, or boolean")
)
localfunctionTest(Input: string | number | boolean)
AssertStringOrNumberOrBoolean(Input)
-- ...endlocalAssertStructureCombined=TypeGuard.Params(
TypeGuard.Object({
X=TypeGuard.Number();
}):And(TypeGuard.Object({
Y=TypeGuard.Number();
})):And(TypeGuard.Object({
Z=TypeGuard.Number();
}))
)
localfunctionTest(Input: {X: number} & {Y: number} & {Z: number})
AssertStructureCombined(Input)
-- ...end5: context passing (functional constraint): assert that the provided Model a descendant of Workspace
localAssertTestContext=TypeGuard.ParamsWithContext(
TypeGuard.Instance("Model"):IsDescendantOf(function(Context)
returnContext.Referenceend)
)
localfunctionTest(Root: Model)
AssertTestContext({Reference=workspace}, Root)
-- ...endlocalAssertTestOptional=TypeGuard.Params(
TypeGuard.String(),
TypeGuard.Optional(TypeGuard.Vector3())
)
localfunctionTest(X: string, Y: Vector3?)
AssertTestOptional(X, Y)
-- ...endlocalAssertValidTest=TypeGuard.Params(
TypeGuard.Instance("Player"):IsDescendantOf(game:GetService("Players")),
TypeGuard.Object({
P=TypeGuard.Number():IsAValueIn({1, 2, 3, 4, 5});
Q=TypeGuard.Number(-100, 100):Integer();
R=TypeGuard.Array(TypeGuard.String()):MaxLength(100);
S=TypeGuard.Object({
Key1=TypeGuard.Optional(TypeGuard.String());
Key2=TypeGuard.Enum(Enum.Material);
}):Strict();
T=TypeGuard.Number():IsInfinite():Negate():IsClose(123, 0.5):Negate(); -- "number should not be infinite and should not be close to 123"
}):Strict()
)
SomeRemoteEvent.OnServerEvent:Connect(function(Player: Player, TestData: {P: number, Q: number, R: {string}, S: {Key1: string?, Key2: Enum.Material?}, T: number})
AssertValidTest(Player, TestData)
-- ...end)8: Instance filtering via wrapping check into predicate: find all alive Humanoids whose characters are not tagged with "Ignore"
localIsHumanoidAlive=TypeGuard.Instance("Model", {
Humanoid=TypeGuard.Instance("Humanoid", { -- Scans children recursivelyHealth=TypeGuard.Number():GreaterThan(0); -- Scans properties
});
}):HasTag("Ignore"):Negate():WrapCheck()
localAliveHumanoids=SomeTableLibrary.Filter(Workspace:GetChildren(), IsHumanoidAlive)localInstances=Instance.new("Model")
localPart1=Instance.new("Part")
Part1.Name="Part1"Part1.Parent=InstanceslocalPart2=Instance.new("Part")
Part2.Name="Part2"Part2.Parent=InstanceslocalChecker=TypeGuard.FromTemplate({
X=1;
Y=2;
Z=3;
P= {
Q=Vector3.new();
R=Instances;
};
Arr= {1, 2, "X", "Y"}; -- Accepts strings or numbers
})
-- ^ created a deep Object TypeCheckerlocalAny=TypeGuard.BaseAny()
localSerialize1=Any:Serialize({
X=1;
Y=2;
P= {"AHHHH", "----", { Q=true;
R=false;
}};
})
print(Any:Deserialize(Serialize1))
localTestObject=TypeGuard.Object({
X=TypeGuard.Number(0, 100);
Y=TypeGuard.Number(0, 10):Integer();
Z=TypeGuard.String():MaxLength(1000);
W=TypeGuard.Optional(TypeGuard.Object(TypeGuard.Boolean(), TypeGuard.String()));
})
localSerialize2=TestObject:Serialize({
X=1;
Y=2;
Z="------------";
W= {
[true] ="H";
[false] ="H";
};
})
print(TestObject:Deserialize(Serialize2))Avoid 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.