How could I check to see if an instance has a property without using an Instance.new() statement?

Hold on, before you read the 17 paragraph miniature community tutorial I’ve prepared for you, I’ll dumb down the question for you: how could I check to see if an instance has a property without using an Instance.new() statement? If your wondering why I would use an Instance.new() statement in the first place, or by what I even mean, or are just *slightly unsure, then just go ahead and read the 17 paragraphs. Should only take a few minutes (depending on how fast you read) and should thoroughly explain some of my thought process.
Oh yeah, one last thing, the script functions as intended, it’s not a problem with the results. It’s just that crashing everything after a fraction of a second after hitting run isn’t ideal.

  1. I’m trying to achieve a table containing all the referenceable properties of every instance via an API-Dump. Don’t ask why, won’t help.

  2. A singular Instance.new() statement used to briefly create an object and check if a property is referenceable is enough to crash studio and the server.

  3. I have experimented with replacing the Instance.new() statement with an empty table (which does not error in this use case, just makes the section of the script ineffective and useless, while still allowing me to debug) resulting in the server and studio not crashing.

The reason why I’m using Instance.new() in the first place is because it creates an object, this and that the script will error when I try to reference a property that isn’t accessible/referenceable via script or outright does not have.
Since I have to include inheritance in my property fetching script (unless the only property a part has is “Shape”), I also have to include the properties of the classes it inherits from, and the classes those inherit from, and so on.
This leads to a simple part, amassing a total of 85 properties, from each of the classes it inherited from.
image
image
image
Now, most of these properties actually can be accessed via directly referencing them to the part. The problem is that, some properties for example “Pivot Offset Orientation” and “Pivot Offset Position”, are actually components of other properties. In this case, they are components of the “Pivot Offset”. If you were to edit “Pivot Offset”, both “Pivot Offset Orientation” and “Pivot Offset Position” would change respectively.

This means that if a script were to try and access one of the components of a property, it might error. You may be thinking “why don’t you just write that script specifically not to do that?” A part is one class. What I’m trying to do is get the properties of *every class.

Ok, now that you hopefully understand, let’s (finally) discuss how we would even check all this mumbo jumbo for if you can directly reference a property.

Well, remember earlier how we discussed how a script would error when referencing properties that don’t exist or can’t be directly referenced? We can actually use that to our advantage. I’m gonna assume you know how pcalls work, if you don’t; their actually quite simple.

They basically tell you if a chunk of code runs without erroring, or errors and then provides you with the error message (in oversimplified terms).

If you didn’t know, calling part["Size"] is the same as calling part.Size. We can use this to plug in variables (provided that they are strings) into the property parameter.
Combining this with a pcall gets us something looking like this:

local partHasProperty, errorMessage = pcall(function()
	local t = part[property] --[[  let's say for example, property = "Size"  ]]
end)

And since the first return value from a pcall is actually a boolean, we can just go

if partHasProperty then
	--do something
end

Now that we’ve established how to check if something has a certain property, it’s time to throw you in the deep end.

local ClassData = {}

local proxyAddress = "roproxy.com"
local API = game:GetService("HttpService"):JSONDecode(game:GetService("HttpService"):GetAsync("http://setup."..proxyAddress.."/"..game:GetService("HttpService"):GetAsync("http://setup."..proxyAddress.."/versionQTStudio").."-API-Dump.json"))

for _, class in pairs(API.Classes) do
	local propertyTable = {Name = class.Name, Superclass = class.Superclass, Properties = {}}
	for _, property in pairs(class.Members) do
		if property.MemberType == "Property" then
			table.insert(propertyTable.Properties, property.Name)
		end
	end
	ClassData[class.Name] = propertyTable
end

for _, class in pairs(ClassData) do --[[  inherit properties from all superclass ancestors  ]]
	local unreferencableProperties = {}
	if class.Tags and class.Tags.NotCreatable then else
		local object = false
		pcall(function()
			object = Instance.new(class.Name)
		end)
		if object then
			local current = class
			while current.Superclass and (current.Superclass ~= "<<<ROOT>>>") do --[[  <<<ROOT>>> is the highest class in the class hiechary  ]]
				current = ClassData[current.Superclass]
				for i, propertyName in pairs(current.Properties) do
					if not(table.find(class.Properties, propertyName)) then
						local hasProperty,_ = pcall(function() --[[  check if property is referenceable  ]]
							local t = object[propertyName]
						end)
						if hasProperty then --[[  prevent unreferenceable properties from being added  ]]
							table.insert(class.Properties, current.Properties[i])
						else
							table.insert(unreferencableProperties, current.Properties[i]) --[[  for debugging  ]]
						end
					end
				end
			end
			pcall(function()
				object:Destroy()
			end)
		end
	end
	if #unreferencableProperties > 0 then
		print(unreferencableProperties, class.Name) --[[  for debugging  ]]
	end
end

print(ClassData)
print(ClassData.Part)

Now if you go to the part that says --[[ inherit properties from all superclass ancestors ]], you’ll find an Instance.new() statement. This is the very Instance.new() statement I was talking about 200 paragraphs earlier that is able to single-handedly crash my studio and the server. It’s probably because there’s an obscene amount of classes in roblox (you got the ones you use every day, and the ones you didn’t even know existed). And for each one of those classes that are creatable via an Instance.new() statement, I created it to do the property reference check thing. You can also see a object:Destroy() at the bottom after it’s done with it, everything still crashes, unnoticeable difference.

So to dumb this entire post down, how could I check to see if an instance has a property without using an Instance.new() statement? Also if there are any tips how to achieve the same functionality without having so many… nested for loops all over the place that would also be greatly appreciated.

If you still don’t understand go check out these posts:

There is a quick and dirty way shown here:

2 Likes

I know, in fact that’s the way I use and explain in the post. The problem is, is that it requires an instance to use. And to get an instance I would need to use Instance.new(). And if I use instance.new() the script crashes as mentioned before.

I’ve found a whole dictionary full of all the roblox instances and their properties before. I can’t remember where I got it from but I think looking up “roblox instances and properties dictionary” might work.
Just store it in a module and then call it whenever you need to index it. Or simply make that a function in the module.

Are you taking about this?

1 Like