The editor is giving me warnings for using table.pack
and table.unpack
:
table.pack
's telling me: W000: This function must be called with self. Did you mean to use a colon instead of a dot?
table.unpack
's telling me: W000: Type mismatch (free22841-3, free22841-3) => boolean | nil and number
Didn’t see this specific message posted here yet after scrolling though, sorry if its already posted and I missed it:
I am not going to lie, I dislike the syntax in its entirety, it could have been done way better and it isn’t what I wanted.
I was hoping for code that looked more like this:
local custom_types = {
type entity_type = {name = string; character = Instance; health = integer;}
}custom_types.entity_type new_entity(name = “john”, character = Instance.new(“Model”); health = 100);
I wished you did more than making Lua look like Rust.
First of all, I want to say that I am really glad they finally released this, I had been looking forward to this update. Although I think it still has some issues with Object Oriented code.
It is unable to find methods of an object when those methods are set using : instead of the regular . I am not sure if that’s a problem on my part or if it has not been implemented yet.
Although I am really hyped to check this all out
What are the performance implications for this update? In (generally) faster lower level languages, you declare types so the compiler knows how much memory it needs to allocate to store a variable. One of the features of a higher level interpreted language is the ability to have a variable which can be declared as one type and change to another type. Another feature is ease of entry: you don’t even have to understand the difference between two different types.
In the case of this update, it does not seem like it was done for performance improvement as “number” is not something that can be used to determine a variable’s size. This is obviously a feature for convenience.
I am pretty sure they introduced so it’s easier for developers to work together on the same code. It’s for consistency and convenience plus it makes code easier to read.
Yeah, I get that. I was only questioning what impact this would have on runtime performance. Would performance be sacrificed for this convenience?
Alright, so what brave soul is gonna go fork luacheck
and make it work with this? That way we can get this feature in VS Code. I’m not doing it lol.
Are we going to see types like Player
and Model
or data types are the only ones we will see (as of the beta)?
Player, Model, etc should already work in the beta.
I would want to add a small suggestion to have the return type definition have same syntax as for other expressions.
Example:
type MyFunction = (string): (boolean, number)
This is also the syntax that Nim language has chosen and it looks really neat:
def square(x: int): int = x*x
The update is neutral on runtime performance - type annotations don’t affect generated code. We have future plans to optimize based on type information but have not done that yet.
That said, with strict mode you can probably remove the runtime type assertions which will result in performance improvements.
What about for RemoteEvents and RemoteFunctions? Can we remove type assertions there?
This is a great question! The answer is “no”, and we should be more explicit about documenting this.
Type annotations are a tool that helps you make sure your code is correct, when the callers are respecting the type contract. We will statically check that the contract is upheld by all callers.
A remote communication boundary is one where on the other side there’s an entity you don’t control - an exploiter. They are free to manufacture arbitrary arguments to remote functions/events, and we have no way (right now) of ensuring the type safety there.
Moreover, in a remote function, you may want to check more than just the type of the value - if there are any useful validity checks that check the actual value, such as “the damage is between 0 and 10”, you should do so as well. This update doesn’t help with that.
That is reasonable. I myself (despite asking about it) don’t really see any prominent use cases for a constant
keyword except the want of skimming quickly over my code to know that the variable I’m looking at never changes.
Of course I could simply just store my variables in a table with a __newindex
metamethod to emulate this behavior, or I could just prefix or suffix my variables with a _CONSTANT
identifier and just make sure to not attempt to reassign those values.
In addition to my earlier post highlighting issues with untyped code (I hope it doesn’t get lost in the wayside ), the type system needs a solid way of exporting types between modules.
Admittedly, I’m not sure how this will perform, since I’d imagine it will take the binder a second to cache all type symbols between modules. But, if changes in one module will only affect its dependents in script analysis, this may be feasible. I suppose the real issue is when you have lots of modules dependent on a single module. Then you’ll probably have to show some loading state for script analysis if there are performance issues here.
I don’t quite like the idea of exporting every type defined in a module unless there’s an explicit keyword for doing so (i.e. export type
);
One way you could do it is by adding the typeof
operator, which only works in type expressions (Similarly, in TypeScript, typeof() is both a function and a keyword that only works in type expressions). This would allow you to export certain types from a module by accessing
local Module = require(static.path.to.module)
type ImportedType = typeof Module.ExportedValue
type ModuleType = typeof Module
However, this method is a bit hacky, and I think there should be a dedicated solution like export type
(in addition to typeof
).
One thing I would really love to see would be “AmbientScripts” or “TypeScripts” which only allow types to be defined on them (which can then be imported by other scripts via require
, a comment directive, or some other special function that only affects static code). It would be even better if these ambient scripts allowed circular dependencies in some way, since they only convey type information, such as class headers. For example, a parent and child class may reference each other’s type, even if they might not both need to construct each other. An AmbientScript could be used as a guarded header in this case; AmbientScripts could also be global, but this would probably clutter things too much, and Roblox has its strengths in modular code.
The way TypeScript does this is worth looking into, and it seems like this type system might not support a deferred complete binding of symbols (I see right now the metatable types aren’t particularly robust or user-friendly, being typed like {|__meta: {__index: <CYCLE>}|}
.
It also looks like this isn’t yet supported, which is really what would be necessary for ambient (type statement only) scripts to be useful:
type C = {[any]: A}
type A = string
ATTENTION
Because of the compatibility issue with as
pseudo-keyword and existing scripts, we may have to disable type annotation support on client/server. However the beta is still on!
Please DO NOT publish places with type annotations just yet as they will not work on production!
However, please continue to experiment in Studio and give us feedback. We are reading everything and will be fixing reported bugs and discussing syntax / semantics issues some people brought up.
We have updated the top post to indicate this.
I can assign a BodyVelocity type variable to the baseplate with no warning. Is this something that will change with the game hierarchy knowledge necessary for module support, or is this a bug?
Roblox Lua is my favorite language again.
Big question: are these types first class? It’d be really cool to be able to make type constructors but that might damage type inference ability. Maybe if you had a type constructor, something like
function LinkedList(t : Type) => Type
return type {
head : t,
--consideration: this would have to be evaluated lazily due to unbounded recursion for this to work, maybe even as late as type-check time.
tail : LinkedList(t)?
}
end
I love it already! Been waiting for something like this for a while. I hope in the future this can be extended to userdata for some really good intellisense.