Generic Table Argument

I have a function that takes in a generic parameter.
How would I make it so I could constrain the generic to be a table/dictionary?

--!strict
function takesInGenericDict<T>(items: { T }): ()
  local key = "Hello"
  for _, item in items do
    print(item[key]) -- Type Error: Expected type table, got 'T' instead
  end
end

You mean array/dictionary?
Just don’t use generics?
All they do is add confusion.

2 Likes

A little type-gymnasticy but it works in my case!

--!strict
function takesInGenericDict<T_Item>(item: T_Item): T_Item
  type T_ItemTable = T_Item & { }
  local key = "Hello"
  print((item :: T_ItemTable)[key])
  return item
end
1 Like

Was about to mention using intersection. This is the only way as far as I know, because constraints for generic parameters haven’t been added yet, so you have to instead constraint the arguments or variables that use them.

By the way, I think this is a bit more compact:

--!strict
function takesInGenericDict<T_Item>(item: T_Item & {}): T_Item
	local key = "Hello"
	print(item[key])
	return item
end

EDIT: Unfortunately it isn’t pretty useful, because item[key] just ends up being an error type.

1 Like

Awesome! I’ll be sure to mark this as the solution. I do really hope they consider constraints, it’d certainly make my life a lot easier😄

I am not sure for what or why you are using generics here, but if the structure of your dictionary is fixed, then I highly recommend you use this instead:

--!strict
function takesInGenericDict<V>(items: { { [string]: V } })
	local key = "Hello"

	for _, item in items do
		local val = item[key]
		print(val) -- val is of type V
	end
end

Now instead of the value being an error type, it’s the generic parameter you take in for the type of your values and you can actually do stuff with the generic parameter. Hope this helps.

120 Likes

The generic is just going to be an object type, whose members will almost always have different types. Technically I could also make item a { [string]: any } (removing the generic parameter), but then each time I call the function I’d also need to cast the result back into the original object type!! I’d just rather do the casting in the function.

type Item = { [string]: any }
function takesInDict(item: Item): Item
  local key = "Hello"
  print(item[key])
  return item
end

type MyObject = {
  Hello: number,
  World: string, 
} -- pretend this is a metatable oop type

local function takesInMyObject(item: MyObject): MyObject
  -- do something
  return item
end

local myObjectInstance: MyObject = { Hello = 12, World = "Hi" }
takesInMyObject(takesInDict(myObjectInstance) :: MyObject)
-- I'd need to do this cast each time i'd call takesInDict so I don't get type errors

Also, just as a side, have you noticed that your reply has 119 likes despite the forum having 47 views? LOL

Oh, alright. I guess that works.

I went to sleep last night, and woke up to this stupidly large number. At first I thought it was a mistake so I refreshed the page and it’s still there?

If you expand it, you will see a bunch of bots. I have no idea who did this or why, all I can say is I am very scared. Giving someone 119 likes on a post with 59 views is not a mortal ability. :fearful:

Send help. :sob: :pray:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.