Hey! I’m beginning to dive into type checking not just for my own organizational skills, but so I can understand other scripts and how to dissect them for my personal understanding. Right now, I want to learn how to be able to alter values OUTSIDE of the module script using types so that things can be easier to read.
Here is what I am currently working on, I have an ability script that makes the module script fire and then the module itself.
Hitbox Starter: (Local Script)
local RS = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")
local hitboxModule = require(RS:WaitForChild("HitboxModule"))
UIS.InputBegan:Connect(function(input, gameProcessed)
if gameProcessed then return end
if input.KeyCode == Enum.KeyCode.Q then
local hitbox = hitboxModule.CreateHitbox()
hitbox.HitboxMode = "Constant"
hitboxModule.StartHitbox()
end
end)
Hitbox Module: (Module Script)
--!strict
local clientBox = {}
clientBox.__index = clientBox
export type Attributes = {
HitboxMode : string
}
function clientBox.CreateHitbox()
local self = setmetatable({} :: Attributes, clientBox)
self.HitboxMode = "Default"
--print(self)
return self
end
function clientBox.StartHitbox(self : Attributes)
local mode = self.HitboxMode
if mode == "Constant" then
print("Mode is Constant")
end
end
return clientBox
In this example, I want to be able to set the mode of the hitbox to, “Constant” and then have it print out what the current mode is and every time I try to test, I get either nil or an error regarding nil.
So how would I make, for the sake of this example, a simple module script where I create a hitbox, change some of the values via types and then have that value be reflected in another function? It’s a little more advanced than what I’m used to be as stated earlier, it’s something I’d like to understand to better my work!
The error you’re getting has nothing to do with types. You’re just not passing a reference to the instance of clientBox that the StartHitbox function expects. You can fix this in a few different ways:
In “Hitbox Starter”, pass in the reference to the StartHitbox function call
local hitbox = hitboxModule.CreateHitbox()
hitbox.HitboxMode = "Constant"
hitboxModule.StartHitbox(hitbox)
Adjust the syntax to use the : operator - which absolves the need for an explicit self parameter
--In "Hitbox Module"
function clientBox:StartHitbox() --The type here isn't technically correct (I'll address later)
local mode = self.HitboxNode
if mode == "Constant" then
print("Mode is Constant")
end
end
Types and type-checking especially for OOP / metatables is in a bit of a volatile state right now. There is a beta out called the “New Luau type solver” which attempts to mitigate some of the pain points with the current type solver. Under the beta, you can do something like this:
--!strict
local MyClass = {}
MyClass.__index = MyClass
export type MyClassInstance = setmetatable<{
Name: string
}, typeof(MyClass)>
function MyClass.new(name: string): MyClassInstance
local self = setmetatable({
Name = name,
}, MyClass)
return self
end
function MyClass:PrintName()
--[[
NOTE: As of writing this post, the beta type solver can act strange about the type of `self`
A band-aid fix at the moment is to reassign self as a local variable and cast, like the line below
]]
local self = self :: MyClassInstance
print(self.Name)
end
return MyClass
(See here for the method without the beta type solver)
local module = {}
module.__index = module
function module.new(data)
local self = setmetatable({}, module)
self.data = data
return self
end
function module:doSomething()
local data = self.data
...
end
Handler:
local module = require(...)
local object = module.new(data)
object:doSomething()
print(object)
Thanks for taking your time to explain it, the changes you’ve made make more sense to me now than what they did before!
Currently however, I am trying your 2nd solution, (changing the . to the : in the specified spots) but whenever I attempt to print mode from the start hitbox function, it is returning nil and not printing the, “Mode is constant” print statement either. I believe I wrote it the same exact way yes?
local RS = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")
local hitboxModule = require(RS:WaitForChild("HitboxModule"))
UIS.InputBegan:Connect(function(input, gameProcessed)
if gameProcessed then return end
if input.KeyCode == Enum.KeyCode.Q then
local hitbox = hitboxModule.CreateHitbox() --East98 Solution
hitbox.HitboxMode = "Constant"
hitbox:StartHitbox()
end
end)
--!strict
local clientBox = {}
clientBox.__index = clientBox
export type Attributes = {
HitboxMode : string
}
function clientBox.CreateHitbox()
local self = setmetatable({} :: Attributes, clientBox)
self.HitboxMode = "Default"
--print(self)
return self
end
function clientBox:StartHitbox() --East98 solution
local mode = self.HitboxNode
print(mode)
if mode == "Constant" then
print("Mode is Constant")
end
end
return clientBox