-
Notifications
You must be signed in to change notification settings - Fork 393
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
Generic typing fails on complex class #392
Comments
This is likely because you need to use explicit self to type table-based OOP code instead of using If that doesn't help, please post source code for this example. |
Yeah :( It's the same issue we've identified in upcoming |
Is there a potential for inherited types in the future? i.e. using T, but inherting T from a Table type, or others? Essentially allowing the type T to be copied, but only if it satisfies the conditions of inherited types i.e. local function copy<T: {}>(tbl: T): T
--....
end |
Unsure what you mean by specializing exactly - this already happens during instantiation, but the issue is that table.freeze currently has the following type signature:
Which is to say, it accepts a dictionary that maps K to V and returns the same - which is more constrained than a fully general table type, which we don't have atm. If we had constrained generics with "table" constraint, we'd be able to say something like
Which would mean "table.freeze returns the table with the exact same shape as was passed in, but is only valid when T is a table type". |
Yes this is exactly what I was referring to, and it also helps with other objects. local function doSomething<T: Instance>(part: T): T
--....
end
print(doSomething(workspace).CurrentCamera) --type can be resolved
-- if Instance was used, the type information would be dropped/lost
print(doSomething("hello")) --invalid type parameter
-- if plain generic templating was used, the type information would not be sufficient enough to indicate invalid arguments local function doAnotherThing<T: (Vector3, number)>(a: T, b: T) -- faster way of defining ((Vector3, Vector3)->() | (number, number)->())
--...
end
local function doAnotherThing<T: {X: number}>(a: T) -- anything with this component
--...
end |
I ran into... something that may be similar to this(?) when trying to infer the type of a Signal class. --!strict
local Signal = {}
Signal.__index = Signal
function Signal.new<A...>(): Signal<A...>
return setmetatable({}, Signal)
end
export type Signal<A...> = typeof(Signal.new())
function Signal.Fire<A...>(self: Signal<A...>, ...: A...)
-- ...
end
function Signal.Connect<A...>(self: Signal<A...>, handler: (A...) -> ()) -- this handler argument is what sets Luau off
-- ...
end
local signal = Signal.new() :: Signal<number, number> -- Cannot cast 'Signal' into 'Signal' because the types are unrelated
signal:Fire(0, 0) I thought, maybe the type definition was the issue - let's try changing it to this: export type Signal<A...> = typeof(setmetatable({}, Signal)) Nope, doesn't work - the only thing that works is sucking it up and forward-declaring all the methods to consuming generics from a higher level (say, a type SignalMeta<A...> = { -- This is disgusting and I hate this
__index: SignalMeta<A...>,
Fire: (self: Signal<A...>, A...) -> (),
Connect: (self: Signal<A...>, handler: (A...) -> ()) -> ()
}
export type Signal<A...> = typeof(setmetatable({}, ({} :: any) :: SignalMeta<A...>)) I hate forward declaration because Luau usually lends itself to being able to infer everything automatically, giving you a really nice and DRY codebase if you just do the bare minimum and sprinkle the type syntax around when needed. However generics is a lot to ask from it. The first code block I gave is not actually technically correct - I will note that, as a type system designed for a language where multiple return values is basically a first-class citizen, Luau does an extremely bad job modeling variadics (in my opinion). But that's a story for another day, this is a post about specifically generics. |
Will probably be fixed or at least worked around now given this similar issue |
I expect that the solution to this problem (and problems like it) will come from #863 |
If i try the other typing method, I get this issue.
The text was updated successfully, but these errors were encountered: