Skip to content

Commit 8c9f552

Browse files
Improvements to Typechecking
* Introduces `QueryResult:server()`, `QueryResult:client()`, and `QueryResult:iter()` for better typechecking.
1 parent c1a17c3 commit 8c9f552

4 files changed

Lines changed: 112 additions & 35 deletions

File tree

lib/Connection.luau

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ type ConnectionImpl = {
1010
new: <U...>(callback: (U...) -> ()) -> Connection,
1111
}
1212

13-
export type Connection = typeof(setmetatable({
14-
-- selene: allow(unused_variable)
15-
_callback = function(...) end,
16-
}, {} :: ConnectionImpl))
13+
export type Connection = typeof(setmetatable({} :: ConnectionImpl, {} :: ConnectionImpl))
1714

1815
--[=[
1916
@class Connection
@@ -60,7 +57,7 @@ function Connection.new<U...>(callback: (U...) -> ())
6057
task.spawn(callback, ...)
6158
end
6259

63-
return self
60+
return self :: any
6461
end
6562

6663
return Connection

lib/QueryResult.luau

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,30 @@ export type Identifier = Identifier.Identifier
1515

1616
local read = Identifier.read
1717

18+
type ClientQueryResult<U...> = {
19+
__index: ClientQueryResult<U...>,
20+
__iter: (self: ClientQueryResult<U...>) -> () -> (number, U...),
21+
22+
_snapshot: { IncomingPacket },
23+
_identifier: Identifier,
24+
_senders: { NetServer },
25+
26+
iter: (self: ClientQueryResult<U...>) -> () -> (number, U...),
27+
}
28+
29+
type ServerQueryResult<U...> = {
30+
__index: ServerQueryResult<U...>,
31+
__iter: (self: ServerQueryResult<U...>) -> () -> (number, Player, U...),
32+
33+
_snapshot: { IncomingPacket },
34+
_identifier: Identifier,
35+
_senders: { Player },
36+
_view: "server",
37+
38+
iter: (self: ServerQueryResult<U...>) -> () -> (number, Player, U...),
39+
from: (self: QueryResult<U...>, ...Player) -> QueryResult<U...>,
40+
}
41+
1842
--[=[
1943
@class QueryResult
2044
@since v0.4.0
@@ -37,23 +61,31 @@ local read = Identifier.read
3761
See [Querying Data](/docs/getting-started/routes#querying) for more information.
3862
]=]
3963
type QueryResultImpl<U...> = {
64+
__index: QueryResultImpl<U...>,
65+
__iter: (self: QueryResult<U...>) -> () -> (number, Player | NetServer, U...),
66+
4067
_snapshot: { IncomingPacket },
4168
_identifier: Identifier,
4269
_senders: { Player | NetServer },
70+
_view: "client"?,
4371

44-
__index: QueryResultImpl<U...>,
45-
__iter: (self: QueryResult<U...>) -> () -> (number?, (Player | NetServer)?, U...),
46-
72+
iter: (self: QueryResult<U...>) -> () -> (number, Player | NetServer, U...),
4773
from: (self: QueryResult<U...>, ...(Player | NetServer)) -> QueryResult<U...>,
4874

75+
client: (self: QueryResult<U...>) -> ClientQueryResult<U...>,
76+
server: (self: QueryResult<U...>) -> ServerQueryResult<U...>,
77+
4978
new: (
5079
snapshot: { IncomingPacket },
5180
identifier: Identifier,
5281
senders: { Recipient }?
5382
) -> QueryResult<U...>,
5483
}
5584

56-
export type QueryResult<U...> = typeof(setmetatable({}, {} :: QueryResultImpl<U...>))
85+
export type QueryResult<U...> = typeof(setmetatable(
86+
{} :: QueryResultImpl<U...>,
87+
{} :: QueryResultImpl<U...>
88+
))
5789

5890
local QueryResult: QueryResultImpl<...any> = {} :: QueryResultImpl<...any>
5991
QueryResult.__index = QueryResult
@@ -82,6 +114,8 @@ function QueryResult:__iter()
82114

83115
local filteredSnapshot = {}
84116

117+
local view = self._view
118+
85119
for i = 1, #self._snapshot do
86120
local packet = self._snapshot[i]
87121
if not packet then
@@ -100,18 +134,38 @@ function QueryResult:__iter()
100134

101135
local i = 0
102136

103-
return function()
137+
return function(): ...any
104138
i += 1
105139

106140
local packet = filteredSnapshot[i]
107141
if not packet then
108142
return
109143
end
110144

145+
if view == "client" then
146+
return i, unpack(packet.data)
147+
end
148+
111149
return i, packet.sender, unpack(packet.data)
112150
end
113151
end
114152

153+
--[=[
154+
@method iter
155+
@within QueryResult
156+
157+
An iterator method for typechecking.
158+
159+
```lua
160+
for i, sender, ... in route:query():iter() do
161+
-- ...
162+
end
163+
```
164+
]=]
165+
function QueryResult:iter()
166+
return self:__iter()
167+
end
168+
115169
--[=[
116170
@method from
117171
@within QueryResult
@@ -139,6 +193,40 @@ function QueryResult:from(...)
139193
return self.new(self._snapshot, self._identifier, senders)
140194
end
141195

196+
--[=[
197+
@method client
198+
@within QueryResult
199+
200+
Switches the query to a client view, for typechecking.
201+
The client view will not return a `sender` when iterating.
202+
203+
```lua
204+
for i, ... in route:query():client():iter() do
205+
-- ...
206+
end
207+
```
208+
]=]
209+
function QueryResult:client()
210+
self._view = "client"
211+
return self :: any
212+
end
213+
214+
--[=[
215+
@method server
216+
@within QueryResult
217+
218+
Switches the query to a server view, for typechecking.
219+
220+
```lua
221+
for i, player, ... in route:query():server():iter() do
222+
-- ...
223+
end
224+
```
225+
]=]
226+
function QueryResult:server()
227+
return self :: any
228+
end
229+
142230
--[=[
143231
@function new
144232
@within QueryResult
@@ -153,7 +241,7 @@ function QueryResult.new(snapshot, identifier, senders)
153241
_snapshot = snapshot,
154242
_identifier = identifier,
155243
_senders = senders or {},
156-
}, QueryResult)
244+
}, QueryResult) :: any
157245
end
158246

159247
return QueryResult

lib/SendRequest.luau

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ local isClient = RunService:IsClient()
2525
Allows for modification of queued packets before they're sent.
2626
]=]
2727
type SendRequestImpl = {
28+
__index: SendRequestImpl,
29+
2830
_outgoingQueue: { OutgoingPacket },
2931
_position: number,
3032

31-
__index: SendRequestImpl,
32-
3333
to: (self: SendRequest, recipient: Recipient) -> (),
3434
}
3535

36-
export type SendRequest = typeof(setmetatable({}, {} :: SendRequestImpl))
36+
export type SendRequest = typeof(setmetatable({} :: SendRequestImpl, {} :: SendRequestImpl))
3737

3838
local SendRequest: SendRequestImpl = {} :: SendRequestImpl
3939
SendRequest.__index = SendRequest

lib/init.luau

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,12 @@ export type Configuration = {
5858
5959
See the [Intro](/docs/intro) to get started.
6060
]=]
61-
type RouteImpl<U...> = {
61+
export type RouteImpl<U...> = {
62+
__index: RouteImpl<U...>,
63+
__iter: (self: Route<U...>) -> QueryResult<U...>,
64+
6265
server: NetServer,
66+
6367
_identifier: Identifier,
6468
_configuration: Configuration,
6569
_outgoingQueue: { OutgoingPacket },
@@ -71,32 +75,20 @@ type RouteImpl<U...> = {
7175
Outgoing: ((...any) -> ...any)?,
7276
},
7377

74-
__index: RouteImpl<U...>,
75-
__iter: (self: Route<U...>) -> QueryResult<U...>,
78+
addIncomingMiddleware: (self: Route<U...>, middleware: (...any) -> ...any) -> (),
79+
addOutgoingMiddleware: (self: Route<U...>, middleware: (...any) -> ...any) -> (),
7680

7781
_queuePackets: (Route<U...>, Bridge) -> (),
7882
_updateSnapshot: (Route<U...>, Bridge) -> (),
7983
_processConnections: (Route<U...>) -> (),
80-
addIncomingMiddleware: (self: Route<U...>, middleware: (...any) -> ...any) -> (),
81-
addOutgoingMiddleware: (self: Route<U...>, middleware: (...any) -> ...any) -> (),
82-
send: (self: Route<U...>, U...) -> SendRequest,
83-
query: (self: Route<U...>) -> QueryResult<U...>,
8484

85-
start: (loop: any, { Route<U...> }) -> (),
86-
createHook: ({ Route<U...> }) -> () -> (),
85+
query: (self: Route<U...>) -> QueryResult<U...>,
86+
send: (self: Route<U...>, U...) -> SendRequest,
8787

88-
new: (Configuration) -> Route<U...>,
88+
new: (Configuration?) -> Route<U...>,
8989
}
9090

91-
export type Route<U...> = typeof(setmetatable(
92-
{} :: {
93-
_configuration: Configuration,
94-
_outgoingQueue: { OutgoingPacket },
95-
_snapshot: IncomingQueue,
96-
_currentPlayers: { Player },
97-
},
98-
{} :: RouteImpl<U...>
99-
))
91+
type Route<U...> = typeof(setmetatable({} :: RouteImpl<U...>, {} :: RouteImpl<U...>))
10092

10193
local Route: RouteImpl<...any> = {} :: RouteImpl<...any>
10294
Route.__index = Route
@@ -174,7 +166,7 @@ function Route:send(...)
174166
SendRequest._position = #self._outgoingQueue
175167
setmetatable(sendRequest, SendRequest)
176168

177-
return sendRequest
169+
return sendRequest :: any
178170
end
179171

180172
--[=[
@@ -393,7 +385,7 @@ function Route.new(configuration: Configuration?)
393385
Unreliable = {},
394386
}
395387

396-
return self
388+
return self :: any
397389
end
398390

399391
--[=[

0 commit comments

Comments
 (0)