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.
I’m running into a strange issue with functions and if statements, where the type returned changes from number to number? when comparing the return value using ==.
The incorrect typing only persists within the scope of the if statement, and doesn’t occur when using other comparisons, i.e. ~=, <=, >, etc.
--!strict
function returns_two(): number
return 2
end
function is_two(num: number): boolean
return num==2
end
local my_number = returns_two()
is_two(my_number) --no error, my_number: number
if my_number == 2 then
is_two(my_number) --type error, my_number: number?
end
if my_number < 3 then
is_two(my_number) --no error, my_number: number
end
is_two(my_number) --no error, my_number: number
I first discovered this when using the bit32 library, so I thought it was an issue with those specifically, but it seems to be an issue for any function that returns a number. Replacing the function with a number literal does not produce an error.
...
local my_number = 2
if my_number == 2 then
is_two(my_number) --no error
end
I tried to recreate the issue with strings but it seems to be an issue exclusive to numbers.
--!strict
function returns_hello(): string
return "hello"
end
function is_hello(msg: string): boolean
return msg == "hello"
end
local my_word = returns_hello()
if my_word == "hello" then
is_hello(my_word) --no error occurs
end
there is a problem with autofill and the type checking for generic dictionary type keys using keyof function.
im trying to make it autofill all the possible keys for the table that i pass to the function but there seems to be an issue with using keyof on a generic type, i found a weird/hacky workaround that autofills the keys of the table but still throws an annoying type error because the solver is failing to interpret a string “example” as a singleton string type which is what it should be interpreted as in this context.
--!strict
local function func1<A>(tbl : A, index : keyof<A>)
end
local myTable = {
key1 = 5,
key2 = 6
}
func1(myTable, "key1") -- no autofill (also throws a type error)
-------------------------------------------------------------------------------------------
--// workaround
local function func2<A>(tbl : A)
return function(index : keyof<A>)
end
end
func2(myTable)("key1") -- yes autofill (but still throws a type error)
export type Window<ui> = {
ui: ui,
visible: boolean,
Show: (self: Window<ui>) -> Window<ui>, -- if removed, the type works
}
local win = {} :: Window<Frame>
If I remove the Show: ... line, the type works again. If I get rid of the <ui> generics it also works. Using Show: (self: any) -> any is not really a good idea though.
It’s possible that this is related to an existing issue with the new solver where large types can gum up the works and prevent us from servicing autocomplete requests. If you return to the old solver, do you still have autofill results? Would you be able to provide the script or place file in which this happens, so we can reproduce and fix this issue?
local connection: RBXScriptConnection | nil
local connection2: RBXScriptConnection | nil
local function updateParams(distance: number, exponentialSpeed: number, speed: number)
distance = (primaryPart.Position - inst.Position).Magnitude
exponentialSpeed = math.floor(self.settings.MaxDistance / distance) / 10
speed = self.settings.SpeedModifier * exponentialSpeed
end
inst:GetPropertyChangedSignal("Position"):Connect(function()
task.spawn(updateParams, distance, exponentialSpeed, speed)
end)
primaryPart:GetPropertyChangedSignal("Position"):Connect(function()
task.spawn(updateParams, distance, exponentialSpeed, speed)
end)
connection = RunService.Stepped:Connect(function() --Save some lag
inst.Position = inst.Position:Lerp(primaryPart.Position, speed)
if typeof(connection) == "RBXScriptConnection" then connection:Disconnect() end --Here it throws an error
end)
connection2 = inst.Destroying:Connect(function()
if typeof(connection) == "RBXScriptConnection" then connection:Disconnect() end
if typeof(connection2) == "RBXScriptConnection" then connection2:Disconnect() end
connection = nil
connection2 = nil
end)
It throws a type error for no reason and I can’t figure why.
Error message: “Type function instance union<blocked-274313, nil> is uninhabited This is likely to be a bug, please report it at GitHub · Where software is built”
I can’t report it just yet on the Github page, but I will try to upload the issue on it as soon as possible.
--!strict
local module = {}
local configurations = {
health = 10;
range = 10;
team = "red";
}
type towerType = keyof<typeof(configurations)>
type health = index<towerType, "health">
function test(param: index<towerType, "health">)
end
return module
You are doing something wrong, and the error is correct, yeah. keyof<typeof(configurations)> gives you the types of all the keys of configurations, i.e. "health" | "range" | "team". Each of these is a string literal type (or string singleton type) corresponding to those keys. The index type function computes the result type of indexing its first argument by a value of its second argument type. That is, your index<towerType, "health"> is asking for “what do I get if I index any of the three strings "health" | "range" | "team" by "health"?” The answer is that it would fail since strings cannot be indexed generally (the exception being that you can access the string library through each string’s metatable, but that metatable doesn’t have a property named health either), and so index is rightfully telling you about the error.
Assuming that you wanted to annotate it to take the type of the value in configurations that corresponds to the key health, that looks a little bit different, e.g.
--!strict
local module = {}
-- adding a type alias here to be very explicit about things
type Configuration = { health: number, range: number, team: string }
local configurations: Configuration = {
health = 10;
range = 10;
team = "red";
}
type towerType = keyof<Configuration>
function test(param: index<Configuration, "health">)
end
-- but this should also work, including if you didn't annotate `configurations`
function test2(param: index<typeof(configurations), "health">)
end
return module
--!strict
local Class = {}
local Mt = {} :: Object
Mt.__index = Mt
export type Object = typeof(setmetatable({} :: {
Property : number,
Method : (Object) -> (),
__index : typeof(Mt),
}, Mt))
function Class.new() : Object
local self = setmetatable({}, Mt) :: Object
self -- new and old : self type is Object
return self
end
-- the new typesolver annotates self as unknown here while the old typesolver annotate it as Object
function Mt:Method()
self -- Old : self type is Object | New : self type is unknown
end
return Class
in the old type solver the type of self in the Method is Object while in the new type solver it is unknown
both screenshots are taken inside of the Method method
old:
new:
I may have defined the type incorrectly, but I donot really know
This is a known issue right now, you can mitigate it yourself by explicitly annotating self in the definition, i.e.
function Mt.Method(self: Object)
-- body of the function
end
If you do this, you can still invoke it later with object:Method() just fine.
We know this is not ideal for folks, and plan to implement shared self type inference at some point in the foreseeable future to rectify this and a myriad of other issues with type inference for object-oriented code.