Type checking for beginners!

You can actually fix it by adding a ? at the end, or by doing | nil after number


to solve that,

number | nil looks a bit uglier imo but in essence, it’s the same thing

Furthermore, we can also return multiple arguments by encasing the return with parentheses



Also little PSA but you can use typechecking with metatables as well by using the typeof() function:



Only issue is that it’s a bit useless, I can’t really think of a use case other than this:

Now, we can use this to create some partConstructor type:


Only downside is that the __newindex metamethod doesn’t fire.
Screen Shot 2021-11-24 at 10.24.47 PM

5 Likes

Metatables inherently isn’t a value type, they’re just normal tables assigned to another table to give functionality so I don’t think they would add such

although a solution if you really need to

type func = type(function() end)

type metatable = {
  __index : func | {any},
  __newindex : func : {any},
  __call : func,
  __tostring : func,
  __metatable : string,
  __mode : string
}

local function getmetatable(...) : metatable?
  return getmetatable(...)
end
4 Likes

Big fan of this thread

(types passed into function) -> (types returned by function) can be used to infer function types, for example

image

3 Likes

There is another way to check if a thread is a function that is easier to understand and is shorter:

local IsFunction = string.split(tostring(YourThread),' ')[1] == 'function:'

Edit (31 may): completely wrong, ()->() is far easier.

can you explain the logical thought process of the computer when you tell it to do something using “::” (assertion) because while i can understand the other type operator on a basic level, the way you explained it using “this works” “this does not work” formula for assertion had me on the ropes

1 Like

Great tutorial!
I knew a little about type setting but couldn’t figure out how to define types within Tables for a long time, great lesson. Thank you very much!

1 Like


This does work well.

Only problem I have is how would I get these types globally recognized by server and client scripts?


I found out one of the ways via the Luau documentation (export keyword)

I managed to use this post, coolalex1835’s + 7z99’s reply and the Luau documentation OP linked to construct a rudimentary custom type called “Command” based off of CMDR. It’s a bit confusing to learn this stuff though.

Custom Type - Command

Type Definition Script (ServerScriptService → ModuleScript)

-- Type Definitions
-- Export this type with the Module Script so that we can access it. Not *necessary* but useful just in case
export type executable = (player : Player | nil, args : {string}) -> boolean

export type command = {
	Name : string,
	HasMetatableAccess : boolean | nil,
	Exec : executable,
	metatable : {any} | nil
} | nil

-- Type Constructors
local Command = {}

Command.New = function(name : string, metatableAccess : boolean, Exec : executable, metatable : {} | nil) : command
	local c : command = {}
	c.Name = name
	c.HasMetatableAccess = metatableAccess
	c.Exec = Exec
	c.metatable = metatable
	
	return c
end

return Command

Example Command using the Type Definition:

-- Require the Command Definition 
local c = require(script.Parent.Command)
 
-- Create an Execute Function (that follows the Executable type)
function Execute(p : Player | nil, args : {string} | nil) : boolean
	print(args) 
	return true
end

-- Construct and Return the command
return c.New("test", false, Execute, {})

Third Script to create and execute the command:

local c = require(script.Parent.TestCommand)

c.Exec(nil, {"does", "this", "work", "yet???"}) -- will print the table.

1 Like

Something else to note which I found really cool is that type checking skills also transfer to the Swift Programming Language that was developed by Apple (doing a uni module with it included). This tutorial has been an invaluable tool that has taken me between several programming languages and helped me throughout my time at university so far.

Thanks, Zamd and contributors :heart:.

For those wondering :: asserts a type,

This means in this example:

--!strict

local Value : any = 5

print(Value + 1) -- This will shout at us because we have Value set to any, this means its not sure if this should be possible or not, this is where assertion comes in:

print((Value::number) + 1) -- This will work because we asserted that this would be possible, via setting its type to number.

-- Remember! assertion only applys for that operation if I were to now do

print(Value + 1) -- It would still shout at us

Hope this cleared it up

1 Like

hello, good afternoon, how can I program that when the player makes 10 kills, he can be given the emblem of 10 kills.

wrong category
and just use property changed and in the connected function if the player has 10 kills add your emblem

image
How to set a type for each output of a function if it returns multiple objects? (number, {[kernel]}:number}) doesn’t work

--Example
type Kernal = {
   [kernal]: number
}

local function exampleFunc() : (Kernal, number)
    --...
end

(Kernal, number) tells Luau that the function returns Kernal first, then a number.

Also, on a different note, you don’t have to create a new type, I just do that if the type is complex and repeated.

Can you typecheck nested variables?

local Table = {}
Table.ShouldBeNumber : number = 0 --> error

Any way around this?

2 Likes

Just gonna quickly say that I’m not the biggest fan of that theme you got going there.

I’ve been doing function type checking for a while now, didn’t know there was more functionality to this. Learn something new every day I guess!

You use the type assertion operator

Table.ShouldBeNumber = 0 :: number

I think you added years to my lifespan for helping me with this. Thank you.

1 Like

Can’t you just do this?:

local thread = function()
end
if type(thread) == "function" then
    print("Thread is a function!")
end
1 Like

It probably got answered already but this typehack works to define a metatable type

type Cat = typeof(setmetatable({}::{
  meow: (Cat) -> ()
}, {} :: {
  __tostring: (Cat) -> string
}))