Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generics referencing generics #1161

Closed
hahn-kev opened this issue May 20, 2022 · 4 comments
Closed

Generics referencing generics #1161

hahn-kev opened this issue May 20, 2022 · 4 comments
Labels
feat/LuaCats Annotations Related to Lua Language Server Annotations (LuaCats) question User has a question

Comments

@hahn-kev
Copy link
Contributor

Hi, I'm working on a project where we're using a function to construct classes which allow you to pass in an inheriting class. This function to construct a class looks something like this:

---@generic TBase: table
---@generic T: TBase
---@param baseClass TBase
---@return T
function Class(baseClass, class)
end

basically the class extends the base class, however I'm not sure how to do this with generics. You can see my attempt above with ---@generic T: TBase but that doesn't work.

Is this something that's currently possible or not?

@sewbacca sewbacca mentioned this issue May 20, 2022
@sumneko
Copy link
Collaborator

sumneko commented May 25, 2022

You must use ---@class to declare the structure of the class to avoid accidental injection of fields (and provide correct warnings in the future)

---@class newClass: baseClass
local mt = Class(baseMT)

@sumneko sumneko added question User has a question feat/LuaCats Annotations Related to Lua Language Server Annotations (LuaCats) labels May 25, 2022
@hahn-kev
Copy link
Contributor Author

ahh ok. I was having a problem where it wouldn't determine the type properly when I marked it as a class so that's why I didn't do that.

For example, this works fine

local mt = Class({test = 'str'})
mt.test -- here intellisense knows about the 'test' field

however this does not.

---@class newClass
local mt = Class({test = 'str'})
mt.test -- now intellisense does not know about 'test'

even though this does work fine

---@class newClass
local mt = {test = 'str'}
mt.test -- here intellisense knows about the 'test' field

I looked through the code and there seems to be special handling for when the value of mt is a table, and for some reason the 2nd example does not get compiled into the table properly when it's annotated as a class.

Here the value has the type of select in the second example when it should be possible to determine that it's the table passed into the Class function. Maybe the bind sources aren't being compiled? I'm not sure, I looked through the code but wasn't exactly sure where the issue came from.

@sumneko
Copy link
Collaborator

sumneko commented May 25, 2022

I looked through the code and there seems to be special handling for when the value of mt is a table, and for some reason the 2nd example does not get compiled into the table properly when it's annotated as a class.

Here the value has the type of select in the second example when it should be possible to determine that it's the table passed into the Class function. Maybe the bind sources aren't being compiled? I'm not sure, I looked through the code but wasn't exactly sure where the issue came from.

This semantics is too complex and requires recursive generics.

It is suggested to define it by ---@field.

@hahn-kev
Copy link
Contributor Author

as a work around I figured out I can change the annotations to look like this:

---@generic TBase: table
---@generic T
---@param baseClass TBase
---@param class T
---@return T|TBase
function Class(baseClass, class)
end

basically this says that the Class function returns a value that is either a T or a TBase, which as far as autocomplete is concerned is very similar to the case where T extends TBase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat/LuaCats Annotations Related to Lua Language Server Annotations (LuaCats) question User has a question
Projects
None yet
Development

No branches or pull requests

2 participants