Skip to content

Conversation

@hardlyardi
Copy link

Do not support table-like types with differing read and write types; including, but not limited to
[read-only properties](https://rfcs.luau.org/property-readonly.html). This RFC proposes adding an optional trailing
argument, a string literal type, to each. The current type expression `keyof<TableLike>` will become equivalent to the
expression `keyof<TableLike, "read"> | keyof<TableLike, "write">`.
Copy link
Contributor

@alexmccord alexmccord Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you just do composition? keyof<readonly<T>> and keyof<writeonly<T>> where readonly removes the write modifier, and conversely writeonly with read modifier.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would that work with extern types?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generic type functions sound like the better option here. I don't think there should be any support for extern types since trying to normalize them seems impossible, e.g. readonly<vector> would have to resolve to something wacky like vector & ~{write x: number, write y: number, write z: number} to work. If someone really needs that then they can just use UDTFs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it isn't unrealistic to normalize the read/write access of extern types, it is unrealistic to normalize the extern types themselves. That's what I'm addressing.

Additionally, there are many examples of the dissonance between extern types and table types being harmful to ease-of-use, as well as the development of the language. I think if it can be avoided, you shouldn't need to use a UDTF to get the read/write keys of an extern type. That's a very reasonable use-case for keyof IMO.

Comment on lines +33 to +39
type Meow = {
read purr: true,
}
-- Write Key 'purr' does not exist in type
type Mrrp = index<Meow, "purr", "write">
-- 'true'
type Mrrp = index<Meow, "purr", "read">
Copy link
Contributor

@alexmccord alexmccord Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type T = index<{ write p: number }, "p">

Ugh, index<{ write p: number }, "p"> getting normalized to number is without doubt a bug. index and rawget are intended to only work on the read part!

@alexmccord
Copy link
Contributor

This is actually a bug report, not an RFC, I think. The type system generates types like index<T, K> as part of deferring any unsolved type variables in the new constraint solver, and the fact that index<T, K> can normalize to the write part of the property means the type system will not derive correct types.

@hardlyardi
Copy link
Author

This is actually a bug report, not an RFC, I think. The type system generates types like index<T, K> as part of deferring any unsolved type variables in the new constraint solver, and the fact that index<T, K> can normalize to the write part of the property means the type system will not derive correct types.

This is definitely an RFC. Getting write indices is useful! That said, I'm aware there are a few bugs w.r.t. table-like-types and indexing, not sure how it all plays out yet.

@aatxe
Copy link
Contributor

aatxe commented Jan 1, 2026

The particular part Alex was commenting on, that type T = index<{ write p: number }, "p"> doesn't give never or an error, is definitely a bug, but yeah, the main part of this RFC is a feature request (the ability to ask for the write-types).

@hardlyardi
Copy link
Author

👍 yeap! i just wanted to clarify that it was a real feature request since there's some overlap with a currently weird part of the type system. thanks :3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants