npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@rbxts/reflection

v1.0.1

Published

Library that allows you to work with types in runtime!

Downloads

30

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 {
	...
}