Typechecking generics don't make sense

  1. What do you want to achieve?
    I want to learn what Typecheck Generics are. It is also somehow known as “type alias”.

  2. What is the issue?
    Nothing with any scripts, but I don’t understand how typechecking generics work, how to use them and what they even are.

  3. What solutions have you tried so far?
    I tried but none of it makes sense.

1 Like

I think the way it works is that you can “pass in” the type of data you want to have stored there.
idk to me it seems pretty unique ro a few cases I can only thing of one place in my code where I could use it.

Generics in luau allow you to pass a type as a parameter and the type will be inserted where that parameter is used. They allow the type checking engine to remember the type is so that the linter can enforce the rules accordingly and helps with debugging code easier at times. For example, we can make an array that can only be comprised of elements of one type:

type Array<T> = {[number]: T}

local a: Array<string> = {"Hello", "World", 1} -- 1 can't be added

Note that the “type parameter” doesn’t have to be “T”, it’s just an example: variable names do not matter

At the time to attach a type to a variable, we can pass a type as parameter in the “diamond” operator <> (as referred to in Java, where there is also generics). Now, the table that is being referenced by a can only contain strings, otherwise the linter will throw a warning

Just like function parameters, we can accept multiple of these type parameters in generics:

type Dict<T, V> = { [T]: V }

local a: Dict<string, number> = { Hello = 1, World = 2, 1, Bye = "bye" }
-- The last two elements won't work

Also, we’re not only constrained to pass in primitive types – we can pass in user-defined types too:

type Array = { [number]: any }
type Dict = { [any] : any }
type TwoD_Array<A> = { [number]: A }

local a: TwoD_Array<Array> = { {1, 2, 3} }
local b: TwoD_Array<Dict> = { {Hello = 1, World = "World"} }

All you need to do is think of generics as sort of a function where you can pass a type in as a “parameter” and the result will be a table with the type set anywhere (as the index or value)

3 Likes

I am still confused, what does something equaling something in the parameter table do/mean.

Generics are type argument and they work similarly to normal function arguments but with some extra power. @Rare_tendo demonstrated a great example of how you could use them. Note that you don’t always need to specify eg. <string> with some type, because Luau can infer the generic from usage.

Eg. if you wanted to make a method for an array, you can use generics to make sure it applies to only specific Array types. Like so:

type Array<T> = {[number]: T} -- {[key type]: value type}

local function Sum(array: Array<number>)
   local sum: number = 0

   for n in ipairs(array) do
       sum += n
   end
   
   return sum
end

local stringArray: Array<string> = {"1", "2", "3"}
local numberArray: Array<number> = {1, 2, 3}
local numberArray2: Array<number> = {1, "2", 3} -- Type error

print(Sum(stringArray)) -- Type error
print(Sum(numberArray)) -- 6

You can also use generic functions (Sum<T>) but apparently that feature is not available at the moment.

Generics are not unique to Luau, in fact most if not all type-related features that Luau has are taken from other languages. Here’s a Wikipedia article. Unfortunately Lua isn’t the best fitted language for this, but if you use it right it can save you a lot of time since you don’t have to check that everything is of correct type.