Hello, I’ve discovered a weird bug with typing optionals inside a table, here’s the repro script and error message.
Type Error: Type '{ Model: Model }' could not be converted into 'MyCustomTable'; type { Model: Model }[read "Model"] (Model) is not exactly MyCustomTable[read "Model"][1] (nil)
--!strict
type MyCustomTable = {
Model: Model?
}
local Foo: MyCustomTable = {
Model = Instance.new("Model")
}
In comparison, this declaration causes no error: local Model: Model? = Instance.new("Model")
This is unfortunately a known bug right now with expected types on table literal expressions. You can work around it by casting right now, i.e.
local Foo: MyCustomTable = {
Model = Instance.new("Model") :: Model?
}
We’re working on overhauling the code responsible for this broadly though to resolve these kinds of bugs systematically as well as a number of related crashes that some users have been experiencing in the same codepaths.
--!strict
local Table = {}
local function RemoveKey(Key)
Table[Key] = nil
end
local function AddKey()
local Key = ""
Table[Key] = 1 -- Type Error: Type 'number' could not be converted into 'nil'
end
some remarks:
error goes away if RemoveKey function is defined after AddKey
does not happen if doing Table["Key"] = 1, i.e. defining the index directly instead of through a variable.
Autocomplete gets completely disabled for any of a table’s functions if a table indexes itself inside of a function:
local Table = {
a = 1
}
function Table.Foo()
local Key = ""
local Element = Table[Key]
end
function Table.Bar()
end
-- can no longer autocomplete Foo or Bar
-- can still autocomplete `a` however
minimal repro:
local Table = {}
function Table.Foo()
local Key = ""
local Element = Table[Key]
end
-- can no longer autocomplete Foo
Hello! I’m glad to see some good changes and bugs being fixed for the new type solver, but will there ever be an updated documentation with up-to-date definitions and examples of the types library?
I currently have 2 RFCs open and it’s not easy going through both of them at the same time, lol.
Another question, let’s say I have a function that takes in a dictionary as a parameter. And the output of this function is another table(proxy), but this time the places of certain keys and values have changed.
How would I use type functions to analyze the given dictionary’s key and value types and create a new table type accordingly? (Example: {variable_a: string, variable_b: number} → {key_a: {variable_a: string}, key_b: {variable_b: number}})
Is there a way to hide some properties from showing up in the hint menu? I have decided to go for dynamic typing for my modules manager that is not actually that dynamic - by having a list of modules and their types. (Thanks so much for the keyof<> and index<> types!) The modules, however, have some properties for internal stuff and should not be able to be accessed from the outside of the module. These are the ones with “S3Si_” prefix:
In order to get rid of them, I tried to make an intersection which would set these to nil. As I have found out, intersections work the way that the first type overrides all same-named properties in the following ones, so I have done this:
However, this approach actually makes it even worse - because now there are all available properties with “S3Si_” prefix in the returned module, it makes it even more messy.
I have tried using unknown or never, too, but that didn’t change. However it wouldn’t make sense to hide these types anyways. (I thought never was an equivalent for void in C#, now I know what it trully means.) Since it is common to hide nil values in other languages, I consider this a bug (unless there is a way to do it).
Also, I think I have read it somewhere already but couldn’t find it now, the new type solver still does not recognise singletons (literals) - see the :GetModule() function call. The type of the function is the following, where types is the module containing the “modules” type above: GetModule: <module>(self: S3Si_modules, name: module) -> index<types.modules, module>
The manager does something with these properties but they are useless outside of it.
The S3Si_init and S3Si_load functions are executed by the manager (user should not be able to call these). The rest have some values and functionality assigned by the manager for the library/module itself to use. For example, S3Si_modules holds the manager itself so the libraries/modules can still use :GetModule() without circularly requiring the manager. S3Si_config leads to the library’s/module’s configuration Instance which the user should also not be able to access. In fact, all these properties are locked with a metatable and trying to access them returns a warning. And because they are useless to the user using the library/module, why should he see them?
Type solver fails to recognize type when returning behavior on a function. I am currently struggling to figure out to return the complete type behavior in my struct factory function. It appears that the language does not know how to handle dynamic dispatching of behavior.
Out of curiosity, when will there be a new type solver update? I am facing so many issues right now with the type solver, it is giving me a head ache. The strange orange bar, generics not correctly being inferred, literally losing all autocompletion (yes, all of it)… It’s been too long since we got an update.
The New Type Solver is being updated continuously, every single week, by the Luau team. You can find week-to-week descriptions of the updates in Roblox’s release notes. The only interruption to that since September was our holiday break! We tried to contextualize this in the initial announcement, but the New Type Solver is a sophisticated piece of technology with a ton of moving parts, and while we worked hard to get it into shape to launch the beta, it was never going to be feasible for us to replicate the wildly disparate uses of the type system in the wild by ourselves.
This does mean that our beta does not resemble the typical Roblox beta: this is not a totally finished product that we expect to release soon after the announcement. It’s a continuous effort to iterate on a complex piece of technology with the help of our more adventurous users, and so nobody should feel bad if they decide they’re not in that cohort and they would like to stick to the stability of the old type solver. We will keep you all posted on big changes to the beta as we work towards getting it ready for a general release.
If you’re experiencing specific problems and would like to see them get resolved faster, submitting a bug report that notes it is for the New Type Solver with a clear reproduction, a clear English description of the unexpected behavior, and a clear description of the expected behavior on either Luau’s open source issue tracker or the DevForum bug reports forum helps us considerably in working through issues.