Luau Type Annotation (Type Checking) Error

type GetType = (...any) -> nil | string

function module.GetObjectType(self, object: Model): GetType
	if object:FindFirstChild("ObjectType") and object:FindFirstChild("ObjectType"):IsA("StringValue") then
		return (object:FindFirstChild("ObjectType"):: StringValue).Value
	end 	
	return
end

[]
[]
I’m trying to set type ‘GetType’ to accept variadic arguments as ‘any’ type and return value as ‘nil’ or ‘string’ type. Why does this type-checking return error saying "Type 'string' could not be converted into '(...any) -> string'? If there is any syntax error I made, which did I do?

This is because you have structured your type arguments wrong. saying function(): Type doesn’t declare the type for the function, it declares its return value(s). If you want to define variadic arguments you can do so like this. However, your function does not appear to need or even use variadic arguments so I will not use them.

function module:GetObjectType(object: Model): string?
	local objectType: Instance? = object:FindFirstChild("ObjectType")
	
	if objectType and objectType:IsA("StringValue") then
		return objectType.Value
	end
	return
end
  • Note: The ? after the string return type denotes that it could possibly be nil. This is a shorter notation than string | nil.
  • Note 2: I defined a variable for retrieving the StringValue | Roblox Creator Documentation object and used that instead of using object:FindFirstChild("ObjectType") constantly. It is bad form to call :FindFirstChild multiple times to retrieve the same value while in the same scope.

You can learn more about type-checking in Luau here. It is basically the same as the type-checking system in Python.

A way in which you define the function like you were intending is this:

type GetType = (object: Model) -> string?

local GetObjectType: GetType = function(object)
	local objectType: Instance? = object:FindFirstChild("ObjectType")
	
	if objectType and objectType:IsA("StringValue") then
		return objectType.Value
	end
	return
end
Self parameter and OOP

The self argument you are using won’t work. The reason for this is because you are not using the colon (:) to call the function. Essentially the colon is syntactic sugar in Lua. What this means is that it isn’t necessarily needed, but it does make your code look prettier. Basically it’s the difference between these two functions and function calls:

function module.noColon(self, ...): () -- function without colon
	print(self,"|",...)
end
function module:withColon(...): () -- function with colon
	print(self,"|",...)
end

moduleObject.noColon(self, "Hello World") -- without the colon
moduleObject:withColon("Hello World") -- with the colon
  • Note: The moduleObject variable is an object created by the module, assuming you are trying to use OOP.

These two functions and function calls are essentially the same in function. They are only different in how they appear.

2 Likes

Thanks for your deep and detailed explanation.

But if I were to have a type set to the function itself, should it be looking like this and it’s the only way to achieve it?:

function module.GetObjectType(self, object: Model): string?
	local objectType: Instance? = object:FindFirstChild("ObjectType")

	if objectType and objectType:IsA("StringValue") then
		return objectType.Value
	end
	return
end

return module

What I wanted to achieve in general was - Define a custom type for both argument and return value, and set it for the multiple functions without having to annotate the type to each function.

It’s not the only way to achieve it. My first function I showed is also another way.

Would it not be possible to create a custom type of both arguments and return value and apply it to multiple functions just by annotating the type name to them?

Yes. If you create a type then you can use it as many times as you want.