When should you typecheck?

I know about the benefits of type checking and surprisingly it saves me from a lot of errors that could mess up my games, but when should you actually use typechecking? Should you typecheck every single variable and function you make etc because sometimes I feel like it can get a little messy

I wouldn’t type check every variable per say but typechecking is very useful using them in functions. Creating your own types as well helps a lot!

Maintaining structure and more-immediate implicit understanding of a function with regards to the data it is given and what is expected to be returned.

1 Like

I only use it on variables on which autocomplete doesn’t work properly that’s honestly the only real use case of type checking

The only times that I would use type checking is in case I lose track or get confused and have to retrace my steps…
So, I guess it just depends on how you know your scripts, their functions and how they are written.

Depends on what you mean by typechecking.
If you mean using the type system (type annotations and type inference), you should use it where it’s helpful, such as when writing a function or building a module.

If you mean actually checking the type, you should use it when handling data received from clients, or where an incorrect type can cause an error/bug that cascades down through your whole game/system.

The type system is a powerful tool and can be very helpful when developing, such as providing auto-complete results and accurate type errors from static analysis before you even run the game.
It has several layers, and can go really deep (user-defined type functions!!!), I suggest referring to the Luau typechecking page to learn more.

especially for large games and complex systems, if you want an easier to debug, maintainable, and readable codebase, using the typechecker is 100% necessary, so imo you should always use it. the time investment is completely worth it.

combined with --!strict mode, it makes you make better decisions during designing system architecture (basically means the way modules interact with each other) and builds a strong foundation in the codebase, because everything is easy to use and get back into if you had forgotten how it works. its also great for teams

also, by typechecking, i mean instances where you have type definition files, both global and local, like this:

--ReplicatedStorage.TypeDefinitions

export type ComponentA = {...}
export type ComponentB= {...}
export type ComponentC = {...}

export type SystemA = {
    ComponentA: ComponentA,
    ComponentB: ComponentA,
    ComponentC: ComponentA,
}

… where the types can be accessed anywhere. or, in instances where you want strongly-defined behavior, this is how I personally make a module that uses OOP:

--!strict

export type GunObject = {...}
export type GunMethods = {
	Fire: (self: GunSystem, velocity: Vector3)
}
export type GunSystem = GunObject & GunMethods

local GunMethods = {}:: GunMethods

 -- typechecker warning: Cannot add property 'untypedFunc' to table 'GunMethods'
function GunMethods.untypedFunc()

end

-- all good
function GunMethods.Fire(self: GunSystem, velocity: Vector3) 

end

...

-- gun system constructor
return function()
    -- if this table's format doesn't match the GunObject type, there will be a warning
	local self: GunObject = {...}

	for name, fn in GunMethods:: any do -- typechecker can be annoying sometimes, cast:: any to make it shut up
		self[name] = fn
	end

	return self:: GunSystem
end

there is quite a lot of info about typechecking, and cant fit it all in one message, so do your research and learn a bit from open sourced stuff to help you decide if its worth it for you

1 Like