@rbxts/reflection
v1.0.1
Published
Library that allows you to work with types in runtime!
Downloads
30
Maintainers
Readme
🔮 Roblox TS reflection
Library that allows you to work with types in runtime!
[!WARNING] This library is in beta, so use it with caution, breaking changes are possible.
📦 Installation
To install this package run the following command:
npm i rbxts-transformer-reflection
npm i @rbxts/reflection
⚙ Setup
you need to modify your tsconfig.json
file to enable reflection, modify compilerOptions
{
"plugins": [
{
"transform": "rbxts-transformer-reflection",
"reflectAllCalls": true,
"autoRegister": true
}
]
}
also you can edit transformer settings
| name | description | | - | - | | reflectAllCalls | will automatically reflect all function calls with generics | | autoRegister | will automatically register all types |
📚 API
Macros are functions that are replaced by Transformer with values
Macros
$reflect<C>() // will register C interface
$indefine<C>() // will return unique type id
How to Get the Type
Use function GetType(): Type imported from module @rbxts/reflection.
import { GetType } from "@rbxts/reflection";
interface IFoo {}
class Foo implements IFoo {}
GetType<IFoo>();
GetType<Foo>();
GetType(Foo);
const foo = new Foo();
GetType<typeof foo>();
GetType(foo);
[!WARNING] Reflection system does not support union and intersection types.
Base usage
import { GetType, Type } from "@rbxts/reflection";
interface IAnimal
{
name: string;
}
class Animal implements IAnimal
{
constructor(public name: string)
{
}
}
const typeOfIAnimal: Type = GetType<IAnimal>();
const typeOfAnimal: Type = GetType<Animal>();
Get Type of Generic Type Parameter (runtime)
import { GetType } from "@rbxts/reflection";
function printTypeProperties<TType>()
{
const type = GetType<TType>(); // <<== get type of type parameter TType
print(type.Name)
}
interface SomeType {
foo: string;
bar: number;
baz: Date;
}
printTypeProperties<SomeType>();
Receipt of all types
/* Returns all types declared in the current project */
GetTypes(CurrentAssembly).forEach((_type) => {
print(_type.Name);
});
/* Returns all declared types */
GetAllAssemblies().forEach((assembly) => {
GetTypes(assembly).forEach((_type) => {
print(_type.Name);
});
});
Attributes
The library provides a system of attributes. This system is very similar from the c# language
const MyAttribute = CreateAttribute(
class {
constructor(public param1: number) {}
},
);
@MyAttribute(1)
class MyClass {
@MyAttribute(2)
private field!: number;
constructor(@MyAttribute(1) data: string) {}
}
GetTypes(CurrentAssembly).forEach((_type) => {
if (_type.HaveAttribute<typeof MyAttribute>()) {
const attribute = _type.GetAttribute<typeof MyAttribute>()!;
print(_type.Name, attribute.param1);
}
});
Types
/**
* Object representing TypeScript type in memory
*/
export declare class Type {
readonly Name: string;
readonly FullName: string;
readonly Assembly: string;
readonly BaseType?: Type;
readonly Value?: unknown;
readonly Constructor?: ConstructorInfo;
readonly Interfaces: ReadonlyArray<Type>;
readonly Properties: ReadonlyArray<Property>;
readonly Methods: ReadonlyArray<Method>;
readonly Kind: TypeKind;
IsInterface(): boolean;
IsClass(): boolean;
IsObject(): boolean;
IsTypeParameter(): boolean;
IsEnum(): boolean;
IsPrimitive(): boolean;
GetProperty(name: string): Property | undefined;
GetMethod(name: string): Method | undefined;
}
export enum TypeKind {
Unknown = 0,
Primitive = 1,
Interface = 2,
Class = 3,
Object = 4,
TypeParameter = 5,
Enum = 6,
}
export enum AccessModifier {
Private = 0,
Protected = 1,
Public = 2,
}
export declare class Method {
readonly Name: string;
readonly ReturnType: Type;
readonly Parameters: Parameter[];
readonly AccessModifier: AccessModifier;
readonly IsStatic: boolean;
readonly IsAbstract: boolean;
readonly Callback?: (context: unknown, ...args: unknown[]) => unknown;
}
export declare class Parameter extends Attribute {
readonly Name: string;
readonly Type: Type;
readonly Optional: boolean;
}
export declare class Property {
readonly Name: string;
readonly Type: Type;
readonly Optional: boolean;
readonly AccessModifier: AccessModifier;
readonly Readonly: boolean;
}
export declare class ConstructorInfo {
readonly Parameters: Parameter[];
readonly AccessModifier: AccessModifier;
readonly Callback?: (...args: unknown[]) => unknown;
}
export type Constructor<T = object> = new (...args: never[]) => T;
export interface AttributeMarker<T extends Constructor> {
(...params: ConstructorParameters<T>): (...args: any[]) => any;
readonly __special: "AttributeMarker";
readonly __instance: InstanceType<T>;
}
export class Attribute {
public static Is<T extends AttributeMarker<any>>(attributeData: unknown): attributeData is T["__instance"];
public GetAttributes(): object[];
public GetAttribute<T extends AttributeMarker<any>>(inherit?: boolean): T["__instance"] | undefined;
public HaveAttribute<T extends AttributeMarker<any>>(inherit?: boolean): boolean;
}
🏷 Tags
[!NOTE]
The tags will be redesigned in future versions.
Reflect all calls in file
Allows you to enable reflect system for the entire file if automatic system has been disabled in tsconfig.json
.
/** @globalReflect */
myReflectableFunction<A>()
myReflectableFunction<B>()
Don't reflect calls for file
Allows you to disable the reflective system for the entire file.
/** @nonReflect */
myReflectableFunction<A>() // will not reflect
Don't register types for entire file
Allows you to disable type registration, in the current file.
/** @nonRegister */
// this interface will not be registered in reflection
interface C {
i: number;
}
Enable reflection for one function
Enables reflection system for a specific function.
/** @reflect */
function reflectMe<T>(a: T): T {
...
}