Skip to main content

Janitor

Janitor is a light-weight, flexible object for cleaning up connections, instances, or anything. This implementation covers all use cases, as it doesn't force you to rely on naive typechecking to guess how an instance should be cleaned up. Instead, the developer may specify any behavior for any object.

Properties

CurrentlyCleaning

This item is read only and cannot be modified. Read Only
Janitor.CurrentlyCleaning: boolean

Whether or not the Janitor is currently cleaning up.

SuppressInstanceReDestroy

since 1.15.4
</>
Janitor.SuppressInstanceReDestroy: boolean

Whether or not you want to suppress the re-destroying of instances. Default is false, which is the original behavior.

Functions

new

Janitor.new() → Janitor

Instantiates a new Janitor object.

Is

Janitor.Is(
Objectany--

The object you are checking.

) → boolean--

true if Object is a Janitor.

Determines if the passed object is a Janitor. This checks the metatable directly.

instanceof

Janitor.instanceof(
Objectany--

The object you are checking.

) → boolean--

true if Object is a Janitor.

An alias for Janitor.Is. This is intended for roblox-ts support.

Add

Janitor:Add(
ObjectT,--

The object you want to clean up.

MethodName?boolean | string,--

The name of the method that will be used to clean up. If not passed, it will first check if the object's type exists in TypeDefaults, and if that doesn't exist, it assumes Destroy.

Index?any--

The index that can be used to clean up the object manually.

) → T--

The object that was passed as the first argument.

Adds an Object to Janitor for later cleanup, where MethodName is the key of the method within Object which should be called at cleanup time. If the MethodName is true the Object itself will be called if it's a function or have task.cancel called on it if it is a thread. If passed an index it will occupy a namespace which can be Remove()d or overwritten. Returns the Object.

info

Objects not given an explicit MethodName will be passed into the typeof function for a very naive typecheck. RBXConnections will be assigned to "Disconnect", functions and threads will be assigned to true, and everything else will default to "Destroy". Not recommended, but hey, you do you.

Luau:

local Workspace = game:GetService("Workspace")
local TweenService = game:GetService("TweenService")

local Obliterator = Janitor.new()
local Part = Workspace.Part

-- Queue the Part to be Destroyed at Cleanup time
Obliterator:Add(Part, "Destroy")

-- Queue function to be called with `true` MethodName
Obliterator:Add(print, true)

-- Close a thread.
Obliterator:Add(task.defer(function()
	while true do
		print("Running!")
		task.wait(0.5)
	end
end), true)

-- This implementation allows you to specify behavior for any object
Obliterator:Add(TweenService:Create(Part, TweenInfo.new(1), {Size = Vector3.new(1, 1, 1)}), "Cancel")

-- By passing an Index, the Object will occupy a namespace
-- If "CurrentTween" already exists, it will call :Remove("CurrentTween") before writing
Obliterator:Add(TweenService:Create(Part, TweenInfo.new(1), {Size = Vector3.new(1, 1, 1)}), "Destroy", "CurrentTween")

TypeScript:

import { Workspace, TweenService } from "@rbxts/services";
import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor<{ CurrentTween: Tween }>();
const Part = Workspace.FindFirstChild("Part") as Part;

// Queue the Part to be Destroyed at Cleanup time
Obliterator.Add(Part, "Destroy");

// Queue function to be called with `true` MethodName
Obliterator.Add(print, true);

// Close a thread.
Obliterator.Add(task.defer(() => {
	while (true) {
		print("Running!");
		task.wait(0.5);
	}
}), true);

// This implementation allows you to specify behavior for any object
Obliterator.Add(TweenService.Create(Part, new TweenInfo(1), {Size: new Vector3(1, 1, 1)}), "Cancel");

// By passing an Index, the Object will occupy a namespace
// If "CurrentTween" already exists, it will call :Remove("CurrentTween") before writing
Obliterator.Add(TweenService.Create(Part, new TweenInfo(1), {Size: new Vector3(1, 1, 1)}), "Destroy", "CurrentTween");

AddObject

since v1.16.0
</>
Janitor:AddObject(
Constructor{new(A...) → T},--

The constructor for the object you want to add to the Janitor.

MethodName?boolean | string,--

The name of the method that will be used to clean up. If not passed, it will first check if the object's type exists in TypeDefaults, and if that doesn't exist, it assumes Destroy.

Index?any,--

The index that can be used to clean up the object manually.

...A...--

The arguments that will be passed to the constructor.

) → T--

The object that was passed as the first argument.

Constructs an object for you and adds it to the Janitor. It's really just shorthand for Janitor:Add(Object.new(), MethodName, Index).

Luau:

local Obliterator = Janitor.new()
local SubObliterator = Obliterator:AddObject(Janitor, "Destroy")
-- SubObliterator is another Janitor!

TypeScript:

import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor();
const SubObliterator = Obliterator.AddObject(Janitor, "Destroy");

AddPromise

Janitor:AddPromise(
PromiseObjectPromise--

The promise you want to add to the Janitor.

) → Promise

Adds a Promise to the Janitor. If the Janitor is cleaned up and the Promise is not completed, the Promise will be cancelled.

Luau:

local Obliterator = Janitor.new()
Obliterator:AddPromise(Promise.delay(3)):andThenCall(print, "Finished!"):catch(warn)
task.wait(1)
Obliterator:Cleanup()

TypeScript:

import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor();
Obliterator.AddPromise(Promise.delay(3)).andThenCall(print, "Finished!").catch(warn);
task.wait(1);
Obliterator.Cleanup();

Remove

Janitor:Remove(
Indexany--

The index you want to remove.

) → Janitor

Cleans up whatever Object was set to this namespace by the 3rd parameter of Janitor.Add.

Luau:

local Obliterator = Janitor.new()
Obliterator:Add(workspace.Baseplate, "Destroy", "Baseplate")
Obliterator:Remove("Baseplate")

TypeScript:

import { Workspace } from "@rbxts/services";
import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor<{ Baseplate: Part }>();
Obliterator.Add(Workspace.FindFirstChild("Baseplate") as Part, "Destroy", "Baseplate");
Obliterator.Remove("Baseplate");

RemoveNoClean

since v1.15
</>
Janitor:RemoveNoClean(
Indexany--

The index you are removing.

) → Janitor

Removes an object from the Janitor without running a cleanup.

Luau

local Obliterator = Janitor.new()
Obliterator:Add(function()
	print("Removed!")
end, true, "Function")

Obliterator:RemoveNoClean("Function") -- Does not print.

TypeScript:

import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor<{ Function: () => void }>();
Obliterator.Add(() => print("Removed!"), true, "Function");

Obliterator.RemoveNoClean("Function"); // Does not print.

RemoveList

since v1.14
</>
Janitor:RemoveList(
...any--

The indices you want to remove.

) → Janitor

Cleans up multiple objects at once.

Luau:

local Obliterator = Janitor.new()
Obliterator:Add(function()
	print("Removed One")
end, true, "One")

Obliterator:Add(function()
	print("Removed Two")
end, true, "Two")

Obliterator:Add(function()
	print("Removed Three")
end, true, "Three")

Obliterator:RemoveList("One", "Two", "Three") -- Prints "Removed One", "Removed Two", and "Removed Three"

TypeScript:

import { Janitor } from "@rbxts/janitor";

type NoOp = () => void

const Obliterator = new Janitor<{ One: NoOp, Two: NoOp, Three: NoOp }>();
Obliterator.Add(() => print("Removed One"), true, "One");
Obliterator.Add(() => print("Removed Two"), true, "Two");
Obliterator.Add(() => print("Removed Three"), true, "Three");

Obliterator.RemoveList("One", "Two", "Three"); // Prints "Removed One", "Removed Two", and "Removed Three"

RemoveListNoClean

since v1.15
</>
Janitor:RemoveListNoClean(
...any--

The indices you want to remove.

) → Janitor

Cleans up multiple objects at once without running their cleanup.

Luau:

local Obliterator = Janitor.new()
Obliterator:Add(function()
	print("Removed One")
end, true, "One")

Obliterator:Add(function()
	print("Removed Two")
end, true, "Two")

Obliterator:Add(function()
	print("Removed Three")
end, true, "Three")

Obliterator:RemoveListNoClean("One", "Two", "Three") -- Nothing is printed.

TypeScript:

import { Janitor } from "@rbxts/janitor";

type NoOp = () => void

const Obliterator = new Janitor<{ One: NoOp, Two: NoOp, Three: NoOp }>();
Obliterator.Add(() => print("Removed One"), true, "One");
Obliterator.Add(() => print("Removed Two"), true, "Two");
Obliterator.Add(() => print("Removed Three"), true, "Three");

Obliterator.RemoveListNoClean("One", "Two", "Three"); // Nothing is printed.

Get

Janitor:Get(
Indexany--

The index that the object is stored under.

) → any?--

This will return the object if it is found, but it won't return anything if it doesn't exist.

Gets whatever object is stored with the given index, if it exists. This was added since Maid allows getting the task using __index.

Luau:

local Obliterator = Janitor.new()
Obliterator:Add(workspace.Baseplate, "Destroy", "Baseplate")
print(Obliterator:Get("Baseplate")) -- Returns Baseplate.

TypeScript:

import { Workspace } from "@rbxts/services";
import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor<{ Baseplate: Part }>();
Obliterator.Add(Workspace.FindFirstChild("Baseplate") as Part, "Destroy", "Baseplate");
print(Obliterator.Get("Baseplate")); // Returns Baseplate.

GetAll

since v1.15.1
</>
Janitor:GetAll() → {[any]any}

Returns a frozen copy of the Janitor's indices.

Luau:

local Obliterator = Janitor.new()
Obliterator:Add(workspace.Baseplate, "Destroy", "Baseplate")
print(Obliterator:GetAll().Baseplate) -- Prints Baseplate.

TypeScript:

import { Workspace } from "@rbxts/services";
import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor<{ Baseplate: Part }>();
Obliterator.Add(Workspace.FindFirstChild("Baseplate") as Part, "Destroy", "Baseplate");
print(Obliterator.GetAll().Baseplate); // Prints Baseplate.

Cleanup

Janitor:Cleanup() → ()

Calls each Object's MethodName (or calls the Object if MethodName == true) and removes them from the Janitor. Also clears the namespace. This function is also called when you call a Janitor Object (so it can be used as a destructor callback).

Luau:

Obliterator:Cleanup() -- Valid.
Obliterator() -- Also valid.

TypeScript:

Obliterator.Cleanup()
// TypeScript version doesn't support the __call method of cleaning.

Destroy

Janitor:Destroy() → ()

Calls Janitor.Cleanup and renders the Janitor unusable.

warning

Running this will make any further attempts to call a method of Janitor error.

LinkToInstance

Janitor:LinkToInstance(
ObjectInstance,--

The instance you want to link the Janitor to.

AllowMultiple?boolean--

Whether or not to allow multiple links on the same Janitor.

) → RBXScriptConnection--

A RBXScriptConnection that can be disconnected to prevent the cleanup of LinkToInstance.

"Links" this Janitor to an Instance, such that the Janitor will Cleanup when the Instance is Destroyed() and garbage collected. A Janitor may only be linked to one instance at a time, unless AllowMultiple is true. When called with a truthy AllowMultiple parameter, the Janitor will "link" the Instance without overwriting any previous links, and will also not be overwritable. When called with a falsy AllowMultiple parameter, the Janitor will overwrite the previous link which was also called with a falsy AllowMultiple parameter, if applicable.

Luau:

local Obliterator = Janitor.new()

Obliterator:Add(function()
	print("Cleaning up!")
end, true)

do
	local Folder = Instance.new("Folder")
	Obliterator:LinkToInstance(Folder)
	Folder:Destroy()
end

TypeScript:

import { Janitor } from "@rbxts/janitor";

const Obliterator = new Janitor();
Obliterator.Add(() => print("Cleaning up!"), true);

{
	const Folder = new Instance("Folder");
	Obliterator.LinkToInstance(Folder, false);
	Folder.Destroy();
}

LinkToInstances

Janitor:LinkToInstances(
...Instance--

All the Instances you want linked.

) → Janitor--

A new Janitor that can be used to manually disconnect all LinkToInstances.

Links several instances to a new Janitor, which is then returned.

Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Instantiates a new Janitor object.",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Janitor"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 73,
                "path": "src/init.lua"
            }
        },
        {
            "name": "Is",
            "desc": "Determines if the passed object is a Janitor. This checks the metatable directly.",
            "params": [
                {
                    "name": "Object",
                    "desc": "The object you are checking.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "`true` if `Object` is a Janitor.",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 86,
                "path": "src/init.lua"
            }
        },
        {
            "name": "instanceof",
            "desc": "An alias for [Janitor.Is](#Is). This is intended for roblox-ts support.",
            "params": [
                {
                    "name": "Object",
                    "desc": "The object you are checking.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "`true` if `Object` is a Janitor.",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 98,
                "path": "src/init.lua"
            }
        },
        {
            "name": "Add",
            "desc": "Adds an `Object` to Janitor for later cleanup, where `MethodName` is the key of the method within `Object` which should be called at cleanup time.\nIf the `MethodName` is `true` the `Object` itself will be called if it's a function or have `task.cancel` called on it if it is a thread. If passed\nan index it will occupy a namespace which can be `Remove()`d or overwritten. Returns the `Object`.\n\n:::info\nObjects not given an explicit `MethodName` will be passed into the `typeof` function for a very naive typecheck.\nRBXConnections will be assigned to \"Disconnect\", functions and threads will be assigned to `true`, and everything else will default to \"Destroy\".\nNot recommended, but hey, you do you.\n:::\n\n### Luau:\n\n```lua\nlocal Workspace = game:GetService(\"Workspace\")\nlocal TweenService = game:GetService(\"TweenService\")\n\nlocal Obliterator = Janitor.new()\nlocal Part = Workspace.Part\n\n-- Queue the Part to be Destroyed at Cleanup time\nObliterator:Add(Part, \"Destroy\")\n\n-- Queue function to be called with `true` MethodName\nObliterator:Add(print, true)\n\n-- Close a thread.\nObliterator:Add(task.defer(function()\n\twhile true do\n\t\tprint(\"Running!\")\n\t\ttask.wait(0.5)\n\tend\nend), true)\n\n-- This implementation allows you to specify behavior for any object\nObliterator:Add(TweenService:Create(Part, TweenInfo.new(1), {Size = Vector3.new(1, 1, 1)}), \"Cancel\")\n\n-- By passing an Index, the Object will occupy a namespace\n-- If \"CurrentTween\" already exists, it will call :Remove(\"CurrentTween\") before writing\nObliterator:Add(TweenService:Create(Part, TweenInfo.new(1), {Size = Vector3.new(1, 1, 1)}), \"Destroy\", \"CurrentTween\")\n```\n\n### TypeScript:\n\n```ts\nimport { Workspace, TweenService } from \"@rbxts/services\";\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor<{ CurrentTween: Tween }>();\nconst Part = Workspace.FindFirstChild(\"Part\") as Part;\n\n// Queue the Part to be Destroyed at Cleanup time\nObliterator.Add(Part, \"Destroy\");\n\n// Queue function to be called with `true` MethodName\nObliterator.Add(print, true);\n\n// Close a thread.\nObliterator.Add(task.defer(() => {\n\twhile (true) {\n\t\tprint(\"Running!\");\n\t\ttask.wait(0.5);\n\t}\n}), true);\n\n// This implementation allows you to specify behavior for any object\nObliterator.Add(TweenService.Create(Part, new TweenInfo(1), {Size: new Vector3(1, 1, 1)}), \"Cancel\");\n\n// By passing an Index, the Object will occupy a namespace\n// If \"CurrentTween\" already exists, it will call :Remove(\"CurrentTween\") before writing\nObliterator.Add(TweenService.Create(Part, new TweenInfo(1), {Size: new Vector3(1, 1, 1)}), \"Destroy\", \"CurrentTween\");\n```",
            "params": [
                {
                    "name": "Object",
                    "desc": "The object you want to clean up.",
                    "lua_type": "T"
                },
                {
                    "name": "MethodName?",
                    "desc": "The name of the method that will be used to clean up. If not passed, it will first check if the object's type exists in TypeDefaults, and if that doesn't exist, it assumes `Destroy`.",
                    "lua_type": "boolean | string"
                },
                {
                    "name": "Index?",
                    "desc": "The index that can be used to clean up the object manually.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "The object that was passed as the first argument.",
                    "lua_type": "T"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 180,
                "path": "src/init.lua"
            }
        },
        {
            "name": "AddObject",
            "desc": "Constructs an object for you and adds it to the Janitor. It's really just shorthand for `Janitor:Add(Object.new(), MethodName, Index)`.\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\nlocal SubObliterator = Obliterator:AddObject(Janitor, \"Destroy\")\n-- SubObliterator is another Janitor!\n```\n\n### TypeScript:\n\n```ts\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor();\nconst SubObliterator = Obliterator.AddObject(Janitor, \"Destroy\");\n```",
            "params": [
                {
                    "name": "Constructor",
                    "desc": "The constructor for the object you want to add to the Janitor.",
                    "lua_type": "{new: (A...) -> T}"
                },
                {
                    "name": "MethodName?",
                    "desc": "The name of the method that will be used to clean up. If not passed, it will first check if the object's type exists in TypeDefaults, and if that doesn't exist, it assumes `Destroy`.",
                    "lua_type": "boolean | string"
                },
                {
                    "name": "Index?",
                    "desc": "The index that can be used to clean up the object manually.",
                    "lua_type": "any"
                },
                {
                    "name": "...",
                    "desc": "The arguments that will be passed to the constructor.",
                    "lua_type": "A..."
                }
            ],
            "returns": [
                {
                    "desc": "The object that was passed as the first argument.",
                    "lua_type": "T"
                }
            ],
            "function_type": "method",
            "since": "v1.16.0",
            "source": {
                "line": 237,
                "path": "src/init.lua"
            }
        },
        {
            "name": "AddPromise",
            "desc": "Adds a [Promise](https://github.com/evaera/roblox-lua-promise) to the Janitor. If the Janitor is cleaned up and the Promise is not completed, the Promise will be cancelled.\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\nObliterator:AddPromise(Promise.delay(3)):andThenCall(print, \"Finished!\"):catch(warn)\ntask.wait(1)\nObliterator:Cleanup()\n```\n\n### TypeScript:\n\n```ts\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor();\nObliterator.AddPromise(Promise.delay(3)).andThenCall(print, \"Finished!\").catch(warn);\ntask.wait(1);\nObliterator.Cleanup();\n```",
            "params": [
                {
                    "name": "PromiseObject",
                    "desc": "The promise you want to add to the Janitor.",
                    "lua_type": "Promise"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Promise"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 267,
                "path": "src/init.lua"
            }
        },
        {
            "name": "Remove",
            "desc": "Cleans up whatever `Object` was set to this namespace by the 3rd parameter of [Janitor.Add](#Add).\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\nObliterator:Add(workspace.Baseplate, \"Destroy\", \"Baseplate\")\nObliterator:Remove(\"Baseplate\")\n```\n\n### TypeScript:\n\n```ts\nimport { Workspace } from \"@rbxts/services\";\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor<{ Baseplate: Part }>();\nObliterator.Add(Workspace.FindFirstChild(\"Baseplate\") as Part, \"Destroy\", \"Baseplate\");\nObliterator.Remove(\"Baseplate\");\n```",
            "params": [
                {
                    "name": "Index",
                    "desc": "The index you want to remove.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Janitor"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 323,
                "path": "src/init.lua"
            }
        },
        {
            "name": "RemoveNoClean",
            "desc": "Removes an object from the Janitor without running a cleanup.\n\n### Luau\n\n```lua\nlocal Obliterator = Janitor.new()\nObliterator:Add(function()\n\tprint(\"Removed!\")\nend, true, \"Function\")\n\nObliterator:RemoveNoClean(\"Function\") -- Does not print.\n```\n\n### TypeScript:\n\n```ts\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor<{ Function: () => void }>();\nObliterator.Add(() => print(\"Removed!\"), true, \"Function\");\n\nObliterator.RemoveNoClean(\"Function\"); // Does not print.\n```",
            "params": [
                {
                    "name": "Index",
                    "desc": "The index you are removing.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Janitor"
                }
            ],
            "function_type": "method",
            "since": "v1.15",
            "source": {
                "line": 406,
                "path": "src/init.lua"
            }
        },
        {
            "name": "RemoveList",
            "desc": "Cleans up multiple objects at once.\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\nObliterator:Add(function()\n\tprint(\"Removed One\")\nend, true, \"One\")\n\nObliterator:Add(function()\n\tprint(\"Removed Two\")\nend, true, \"Two\")\n\nObliterator:Add(function()\n\tprint(\"Removed Three\")\nend, true, \"Three\")\n\nObliterator:RemoveList(\"One\", \"Two\", \"Three\") -- Prints \"Removed One\", \"Removed Two\", and \"Removed Three\"\n```\n\n### TypeScript:\n\n```ts\nimport { Janitor } from \"@rbxts/janitor\";\n\ntype NoOp = () => void\n\nconst Obliterator = new Janitor<{ One: NoOp, Two: NoOp, Three: NoOp }>();\nObliterator.Add(() => print(\"Removed One\"), true, \"One\");\nObliterator.Add(() => print(\"Removed Two\"), true, \"Two\");\nObliterator.Add(() => print(\"Removed Three\"), true, \"Three\");\n\nObliterator.RemoveList(\"One\", \"Two\", \"Three\"); // Prints \"Removed One\", \"Removed Two\", and \"Removed Three\"\n```",
            "params": [
                {
                    "name": "...",
                    "desc": "The indices you want to remove.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Janitor"
                }
            ],
            "function_type": "method",
            "since": "v1.14",
            "source": {
                "line": 462,
                "path": "src/init.lua"
            }
        },
        {
            "name": "RemoveListNoClean",
            "desc": "Cleans up multiple objects at once without running their cleanup.\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\nObliterator:Add(function()\n\tprint(\"Removed One\")\nend, true, \"One\")\n\nObliterator:Add(function()\n\tprint(\"Removed Two\")\nend, true, \"Two\")\n\nObliterator:Add(function()\n\tprint(\"Removed Three\")\nend, true, \"Three\")\n\nObliterator:RemoveListNoClean(\"One\", \"Two\", \"Three\") -- Nothing is printed.\n```\n\n### TypeScript:\n\n```ts\nimport { Janitor } from \"@rbxts/janitor\";\n\ntype NoOp = () => void\n\nconst Obliterator = new Janitor<{ One: NoOp, Two: NoOp, Three: NoOp }>();\nObliterator.Add(() => print(\"Removed One\"), true, \"One\");\nObliterator.Add(() => print(\"Removed Two\"), true, \"Two\");\nObliterator.Add(() => print(\"Removed Three\"), true, \"Three\");\n\nObliterator.RemoveListNoClean(\"One\", \"Two\", \"Three\"); // Nothing is printed.\n```",
            "params": [
                {
                    "name": "...",
                    "desc": "The indices you want to remove.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Janitor"
                }
            ],
            "function_type": "method",
            "since": "v1.15",
            "source": {
                "line": 520,
                "path": "src/init.lua"
            }
        },
        {
            "name": "Get",
            "desc": "Gets whatever object is stored with the given index, if it exists. This was added since Maid allows getting the task using `__index`.\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\nObliterator:Add(workspace.Baseplate, \"Destroy\", \"Baseplate\")\nprint(Obliterator:Get(\"Baseplate\")) -- Returns Baseplate.\n```\n\n### TypeScript:\n\n```ts\nimport { Workspace } from \"@rbxts/services\";\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor<{ Baseplate: Part }>();\nObliterator.Add(Workspace.FindFirstChild(\"Baseplate\") as Part, \"Destroy\", \"Baseplate\");\nprint(Obliterator.Get(\"Baseplate\")); // Returns Baseplate.\n```",
            "params": [
                {
                    "name": "Index",
                    "desc": "The index that the object is stored under.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "This will return the object if it is found, but it won't return anything if it doesn't exist.",
                    "lua_type": "any?"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 568,
                "path": "src/init.lua"
            }
        },
        {
            "name": "GetAll",
            "desc": "Returns a frozen copy of the Janitor's indices.\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\nObliterator:Add(workspace.Baseplate, \"Destroy\", \"Baseplate\")\nprint(Obliterator:GetAll().Baseplate) -- Prints Baseplate.\n```\n\n### TypeScript:\n\n```ts\nimport { Workspace } from \"@rbxts/services\";\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor<{ Baseplate: Part }>();\nObliterator.Add(Workspace.FindFirstChild(\"Baseplate\") as Part, \"Destroy\", \"Baseplate\");\nprint(Obliterator.GetAll().Baseplate); // Prints Baseplate.\n```",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "{[any]: any}"
                }
            ],
            "function_type": "method",
            "since": "v1.15.1",
            "source": {
                "line": 598,
                "path": "src/init.lua"
            }
        },
        {
            "name": "Cleanup",
            "desc": "Calls each Object's `MethodName` (or calls the Object if `MethodName == true`) and removes them from the Janitor. Also clears the namespace.\nThis function is also called when you call a Janitor Object (so it can be used as a destructor callback).\n\n### Luau:\n\n```lua\nObliterator:Cleanup() -- Valid.\nObliterator() -- Also valid.\n```\n\n### TypeScript:\n\n```ts\nObliterator.Cleanup()\n// TypeScript version doesn't support the __call method of cleaning.\n```",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 631,
                "path": "src/init.lua"
            }
        },
        {
            "name": "Destroy",
            "desc": "Calls [Janitor.Cleanup](#Cleanup) and renders the Janitor unusable.\n\n:::warning\nRunning this will make any further attempts to call a method of Janitor error.\n:::",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 690,
                "path": "src/init.lua"
            }
        },
        {
            "name": "LinkToInstance",
            "desc": "\"Links\" this Janitor to an Instance, such that the Janitor will `Cleanup` when the Instance is `Destroyed()` and garbage collected.\nA Janitor may only be linked to one instance at a time, unless `AllowMultiple` is true. When called with a truthy `AllowMultiple` parameter,\nthe Janitor will \"link\" the Instance without overwriting any previous links, and will also not be overwritable.\nWhen called with a falsy `AllowMultiple` parameter, the Janitor will overwrite the previous link which was also called with a falsy `AllowMultiple` parameter, if applicable.\n\n### Luau:\n\n```lua\nlocal Obliterator = Janitor.new()\n\nObliterator:Add(function()\n\tprint(\"Cleaning up!\")\nend, true)\n\ndo\n\tlocal Folder = Instance.new(\"Folder\")\n\tObliterator:LinkToInstance(Folder)\n\tFolder:Destroy()\nend\n```\n\n### TypeScript:\n\n```ts\nimport { Janitor } from \"@rbxts/janitor\";\n\nconst Obliterator = new Janitor();\nObliterator.Add(() => print(\"Cleaning up!\"), true);\n\n{\n\tconst Folder = new Instance(\"Folder\");\n\tObliterator.LinkToInstance(Folder, false);\n\tFolder.Destroy();\n}\n```",
            "params": [
                {
                    "name": "Object",
                    "desc": "The instance you want to link the Janitor to.",
                    "lua_type": "Instance"
                },
                {
                    "name": "AllowMultiple?",
                    "desc": "Whether or not to allow multiple links on the same Janitor.",
                    "lua_type": "boolean"
                }
            ],
            "returns": [
                {
                    "desc": "A RBXScriptConnection that can be disconnected to prevent the cleanup of LinkToInstance.",
                    "lua_type": "RBXScriptConnection"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 739,
                "path": "src/init.lua"
            }
        },
        {
            "name": "LinkToInstances",
            "desc": "Links several instances to a new Janitor, which is then returned.",
            "params": [
                {
                    "name": "...",
                    "desc": "All the Instances you want linked.",
                    "lua_type": "Instance"
                }
            ],
            "returns": [
                {
                    "desc": "A new Janitor that can be used to manually disconnect all LinkToInstances.",
                    "lua_type": "Janitor"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 755,
                "path": "src/init.lua"
            }
        }
    ],
    "properties": [
        {
            "name": "CurrentlyCleaning",
            "desc": "Whether or not the Janitor is currently cleaning up.",
            "lua_type": "boolean",
            "readonly": true,
            "source": {
                "line": 52,
                "path": "src/init.lua"
            }
        },
        {
            "name": "SuppressInstanceReDestroy",
            "desc": "Whether or not you want to suppress the re-destroying\nof instances. Default is false, which is the original\nbehavior.",
            "lua_type": "boolean",
            "since": "1.15.4",
            "source": {
                "line": 62,
                "path": "src/init.lua"
            }
        }
    ],
    "types": [],
    "name": "Janitor",
    "desc": "Janitor is a light-weight, flexible object for cleaning up connections, instances, or anything. This implementation covers all use cases,\nas it doesn't force you to rely on naive typechecking to guess how an instance should be cleaned up.\nInstead, the developer may specify any behavior for any object.",
    "source": {
        "line": 38,
        "path": "src/init.lua"
    }
}