Types for Fusion.New, but for normal people

If you use VSCode, you should use Fusion Autocomplete instead. If you don’t, here’s a quick program to generate a type for Fusion.New that contains all of the possible overloads, so you can write code with autocomplete.

type-template.luau:

--!strict
--[[
    This is generated code. Do not modify it.
    
    Re-exports Fusion.New, but with about 300 type overloads.
]]

local Fusion = require(path.to.fusion)

type CanBeState<T> = Fusion.CanBeState<T>

--#INSERT_GENCODE

return Fusion.New :: New

Python program in the same directory:

import json
import dataclasses
from typing import Self


PRIMITIVE_TO_TYPE_MAP = {
    "bool": "boolean",
    "string": "string",
    "int": "number",
    "int64": "number",
    "float": "number",
    "double": "number",
}


DATATYPE_TO_TYPE_MAP = {
    "Content": "string",
    "QFont": "nil",
    "QDir": "nil",
    "BinaryString": "string"
}


ALLOWED_SUPERCLASSES = {"Instance"}


@dataclasses.dataclass
class Property:
    category: str
    name: str


@dataclasses.dataclass
class Instance:
    name: str
    superclass: str
    properties: dict[str, Property] = dataclasses.field(default_factory=dict)
    tags: list[str] = dataclasses.field(default_factory=list)


data_types = json.load(open("API-Dump.json"))
instance_tree: dict[str, Instance] = dict()

assert data_types["Version"] == 1

for instance_json in data_types["Classes"]:
    instance = Instance(
        instance_json["Name"],
        properties={
            member["Name"]: Property(member["ValueType"]["Category"], member["ValueType"]["Name"]) for member in instance_json["Members"] if member["MemberType"] == "Property" and member["Security"]["Write"] == "None"
        },
        superclass = instance_json["Superclass"],
        tags = instance_json.get("Tags", [])
    )
    instance_tree[instance_json["Name"]] = instance


def gen_params(instance: Instance):
    formatted = "{\n"
    
    while instance is not None:
        for name, property in instance.properties.items():
            type: str
            
            match property.category:
                case "Primitive":
                    type = PRIMITIVE_TO_TYPE_MAP[property.name]
                case "DataType":
                    try:
                        type = DATATYPE_TO_TYPE_MAP[property.name]
                    except KeyError:
                        type = property.name
                case "Class":
                    type = property.name
                case "Enum":
                    type = f"Enum.{property.name}"
                case other:
                    raise Exception(f"don't know how to handle {other}")
            
            if " " in name:
                formatted += f"\t\t[\"{name}\"]: CanBeState<{type}>?,\n"
            else:
                formatted += f"\t\t{name}: CanBeState<{type}>?,\n"
        
        instance = instance_tree.get(instance.superclass)
    
    formatted += "\t}"
    return formatted


output = "type New =\n"

for instance in instance_tree.values():
    if "NotCreatable" in instance.tags or "NotBrowsable" in instance.tags or "Deprecated" in instance.tags:
        continue
    
    super = instance.superclass
    while super in instance_tree:
        if super in ALLOWED_SUPERCLASSES:
            break
        else:
            super = instance_tree[super].superclass
    else:
        continue
    
    output += f"\t& ((className: \"{instance.name}\") -> (propertyTable: {gen_params(instance)}) -> {instance.name})\n"


with open("type_template.luau") as template:
    template = template.read()
    print(template.replace("--#INSERT_GENCODE", output))

The program will output the file’s contents to your terminal. Redirect the output like this:

python3 program.py > New.luau

Important:
You’ll need to increase Luau’s complexity limit, or decrease the amount of types included.

  • Increase Luau’s complexity limit
    Set FIntLuauTarjanChildLimit to 0 (LuauTarjanChildLimit with luau-lsp) — if Studio crashes, revert this change

  • Decrease the amount of types included
    Change ALLOWED_SUPERCLASSES in the Python file to only include some useful base classes:

    ALLOWED_SUPERCLASSES = {"GuiBase", "UIBase", "PVInstance", ...}
    

image

4 Likes

Sorry, I should also clarify—you’ll also need to download the Roblox API dump and put it in the same directory as the script. It should be called API-Dump.json.