- Introduced a new endpoint `/api/syncback` for one-click full sync from Roblox Studio to the filesystem, eliminating the need for an active WebSocket connection. - Implemented `SyncbackRequest` and `ServiceChunk` structures to handle service-level properties and child instances during syncback. - Enhanced `encodeService` to include ObjectValue carriers for accurate reference handling and prevent data loss. - Updated the syncback process to utilize Luau-style relative paths for reference attributes, improving path management and consistency. - Integrated session caching in the matching algorithm to optimize performance during syncback operations. These changes significantly improve the live syncback experience, ensuring reliable data synchronization and enhanced performance during development.
2.6 KiB
Leading | and & in types
Status: Implemented
Summary
Allow the use of | and & without any types preceding them.
Motivation
Occasionally, you will have many different types in a union or intersection type that exceeds a reasonable line limit and end up formatting it to avoid horizontal scrolling. Using the English alphabet as an example:
type EnglishAlphabet = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
Or you might just format it for readability:
type EnglishAlphabet = never
| "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m"
| "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
| "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M"
| "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
Currently, there are two solutions to effect it:
- Moving
=to the next line - Keep
=on the line and addneverif using|, orunknownif using&
-- 1) union:
type Result<T, E>
= { tag: "ok", value: T }
| { tag: "err", error: E }
-- 2) union:
type Result<T, E> = never
| { tag: "ok", value: T }
| { tag: "err", error: E }
-- 1) intersection:
type MyOverloadedFunction
= ((string) -> number)
& ((number) -> string)
-- 2) intersection:
type MyOverloadedFunction = unknown
& ((string) -> number)
& ((number) -> string)
OCaml and TypeScript support this same syntax:
type 'a tree =
| Leaf
| Node of 'a tree * 'a * 'a tree;;
type Tree<T> =
| { type: "leaf" }
| { type: "node", left: Tree<T>, value: T, right: Tree<T> };
Design
This type becomes valid Luau syntax.
type Tree<T> =
| { type: "leaf" }
| { type: "node", left: Tree<T>, value: T, right: Tree<T> }
Drawbacks
No drawbacks. The parser change is trivial. Instead of trying to parse a simple type and then calling Parser::parseTypeSuffix, simply sense whether the current lexeme is | or & and directly invoke Parser::parseTypeSuffix with nullptr for the first type and making sure that nullptr does not get pushed into the resulting vector. If the current lexeme is not | or &, then revert to current logic.
Alternatives
Don't do this and accept one of the solutions already mentioned.