Roblox API
roblox-ts provides typings for the Roblox API which are partially handwritten and partially automatically generated.
In general, everything from the Roblox API is available for use, unless it is deprecated or conflicts with TypeScript.
Values
Globals
All global values from the Roblox API are present in roblox-ts typings.
print("Hello World!");
const zero = math.sin(math.pi);
coroutine.wrap(() => {
print("A");
wait(1);
print("B");
})();
You can find a list of available globals and libraries on the Roblox Engine API Reference.
Parts of table
and string
have been intentionally omitted.
Constructors
.new()
functions (like Vector3.new()
or CFrame.new()
) should instead be called with the new
operator.
new T(...)
will always compile to T.new(...)
.
const v3 = new Vector3(1, 2, 3); // compiles to Vector3.new(1, 2, 3)
print(v3.X, v3.Y, v3.Z); // 1 2 3
const part = new Instance("Part");
print(part.Color);
nil
undefined
is a direct replacement for nil
. It can be used both as a type and a value.
Types
Provided Types
Every Roblox class (Instance
, Part
, Humanoid
, Workspace
, etc.) is provided as a global/ambient type. You can use these types to describe variables, function parameters, function return types, and just about anything else in your code.
// note: The type Part could be inferred here if not provided
const part: Part = new Instance("Part");
print(part.Size);
function takesBasePart(basePart: BasePart) {
return basePart.Size.X + basePart.Size.Y + basePart.Size.Z;
}
// we can use any type which inherits from BasePart!
takesBasePart(new Instance("Seat"));
takesBasePart(new Instance("Part"));
takesBasePart(new Instance("WedgePart"));
// Humanoid does not inherit from BasePart, so this will error!
// takesBasePart(new Instance("Humanoid"));
RemoteEvent Types
New roblox-ts users are usually confused why RemoteEvent.OnServerEvent
only allows unknown
arguments.
const remoteEvent = new Instance("RemoteEvent");
// this works fine
remoteEvent.OnClientEvent.Connect((points: number) => {});
// changing unknown to number causes an error!
remoteEvent.OnServerEvent.Connect((player: Player, points: unknown) => {});
The reason for this is because client-to-server networking cannot be trusted. Exploiters or cheaters in your game can fire your RemoteEvent functions with whatever data they want.
If your code is expecting points
to be a number
, but the client sends a nil
value, the server will error. By sending a large number of requests very quickly which result in errors, an exploiter could crash your game server and disconnect all of your players.
Instead, you should assume your inputs can be any possible value and validate the type at runtime using the typeIs
macro:
const remoteEvent = new Instance("RemoteEvent");
remoteEvent.OnServerEvent.Connect((player: Player, points: unknown) => {
if (!typeIs(points, "number")) {
return;
}
// do something with points
});
You can also verify the arguments with a type validation package like @rbxts/t
.
Alternatively, the community has created a few networking libraries which make the experience much nicer!
Exceptions
Deprecated types are usually not provided. Exceptions to this rule are made for API members which do not have a non-deprecated functional equivalent.
One notable exception: Instance.Changed
is not provided as it conflicts with inheritance. Usually, you want to use Instance.GetPropertyChangedSignal()
instead.
import { Workspace } from "@rbxts/services";
Workspace.GetPropertyChangedSignal("DistributedGameTime").Connect(() => {
print(Workspace.DistributedGameTime);
});
If you must use Instance.Changed
, you can workaround this by asserting an intersection type with ChangedSignal
:
function foo(part: Part) {
(part as Part & ChangedSignal).Changed.Connect(name => {})
}
Utility Interfaces
There are a few key global interfaces which make manipulating types easier:
Services
Services
is an interface consisting of a mapping of string name to type for every Roblox service which you can fetch with game:GetService("ServiceName")
.
interface Services {
AnalyticsService: AnalyticsService;
AppUpdateService: AppUpdateService;
AssetCounterService: AssetCounterService;
AssetDeliveryProxy: AssetDeliveryProxy;
// ... many more services!
}
You can get a union of all service names with keyof Services
.
And you can get a union of all service types with Services[keyof Services]
.
type AllServiceNames = keyof Services;
type AllServices = Services[keyof Services];
CreatableInstances
CreatableInstances
is an interface consisting of a mapping of string name to type for every Roblox instance which can be created with Instance.new("ClassName")
.
interface CreatableInstances {
Accessory: Accessory;
Accoutrement: Accoutrement;
Actor: Actor;
AlignOrientation: AlignOrientation;
// ... many more instances!
}
You can get a union of all creatable instance names with keyof CreatableInstances
.
And you can get a union of all creatable instance types with CreatableInstances[keyof CreatableInstances]
.
type AllCreatableInstanceNames = keyof CreatableInstances;
type AllCreatableInstances = CreatableInstances[keyof CreatableInstances];
AbstractInstances
AbstractInstances
is an interface consisting of a mapping of string name to type for every Roblox instance which will never be created. Generally, these are useful for functions that check inheritance like Instance:IsA("ClassName")
.
interface AbstractInstances {
BackpackItem: BackpackItem;
BasePart: BasePart;
BasePlayerGui: BasePlayerGui;
BaseScript: BaseScript;
// ... many more instances!
}
You can get a union of all abstract instance names with keyof AbstractInstances
.
And you can get a union of all abstract instance types with AbstractInstances[keyof AbstractInstances]
.
type AllAbstractInstanceNames = keyof AbstractInstances;
type AllAbstractInstances = AbstractInstances[keyof AbstractInstances];
Instances
Instances
is an interface consisting of a mapping of string name to type for every Roblox instance. It inherits from Services
, CreatableInstances
, and AbstractInstances
. Instances
and also includes any type of Instance which:
- cannot be created with
Instance.new("ClassName")
- cannot be fetched with
game:GetService("ServiceName")
- but can be given a reference to
Examples:
DataModel
is a class that cannot be created or fetched with GetService, but is given by thegame
global valueAnimationTrack
can only be given a reference to via:LoadAnimation()
fromHumanoid
orAnimationTrack
interface Instances extends Services, CreatableInstances, AbstractInstances {
AnimationTrack: AnimationTrack;
BaseWrap: BaseWrap;
CatalogPages: CatalogPages;
DataModel: DataModel;
// ... many more instances!
}
You can get a union of all instance names with keyof Instances
.
And you can get a union of all instance types with Instances[keyof Instances]
.
type AllInstanceNames = keyof Instances;
type AllInstances = Instances[keyof Instances];
Usage with Generics
You can use any of these utility interfaces with generic functions. This is useful for taking an argument string and returning a matching instance type.
import { Workspace } from "@rbxts/services";
function getDescendantsWhichIsA<T extends keyof Instances>(parent: Instance, className: T): Instances[T][] {
return parent.GetDescendants().filter((descendant): descendant is Instances[T] => descendant.IsA(className));
}
const humanoidsInWorkspace: Array<Humanoid> = getDescendantsWhichIsA(Workspace, "Humanoid");