@quenty/rx 13.17.0 → 13.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [13.17.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rx@13.17.0...@quenty/rx@13.17.1) (2025-04-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Add types to packages ([2374fb2](https://github.com/Quenty/NevermoreEngine/commit/2374fb2b043cfbe0e9b507b3316eec46a4e353a0))
12
+
13
+
14
+
15
+
16
+
6
17
  # [13.17.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rx@13.16.2...@quenty/rx@13.17.0) (2025-04-02)
7
18
 
8
19
  **Note:** Version bump only for package @quenty/rx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/rx",
3
- "version": "13.17.0",
3
+ "version": "13.17.1",
4
4
  "description": "Quenty's reactive library for Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -27,19 +27,20 @@
27
27
  "Quenty"
28
28
  ],
29
29
  "dependencies": {
30
- "@quenty/cancellabledelay": "^3.5.0",
31
- "@quenty/canceltoken": "^11.11.1",
32
- "@quenty/ducktype": "^5.8.1",
33
- "@quenty/loader": "^10.8.0",
34
- "@quenty/maid": "^3.4.0",
35
- "@quenty/promise": "^10.10.1",
36
- "@quenty/signal": "^7.10.0",
37
- "@quenty/symbol": "^3.4.0",
38
- "@quenty/table": "^3.7.1",
39
- "@quenty/throttle": "^10.9.0"
30
+ "@quenty/cancellabledelay": "^3.5.1",
31
+ "@quenty/canceltoken": "^11.11.2",
32
+ "@quenty/ducktype": "^5.8.2",
33
+ "@quenty/loader": "^10.8.1",
34
+ "@quenty/maid": "^3.4.1",
35
+ "@quenty/promise": "^10.10.2",
36
+ "@quenty/signal": "^7.10.1",
37
+ "@quenty/symbol": "^3.4.1",
38
+ "@quenty/table": "^3.7.2",
39
+ "@quenty/throttle": "^10.9.1",
40
+ "@quenty/typeutils": "^1.0.1"
40
41
  },
41
42
  "publishConfig": {
42
43
  "access": "public"
43
44
  },
44
- "gitHead": "e8ea56930e65322fcffc05a1556d5df988068f0b"
45
+ "gitHead": "78c3ac0ab08dd18085b6e6e6e4f745e76ed99f68"
45
46
  }
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Observables are like an [signal](/api/Signal), except they do not execute code
3
4
  until the observable is subscribed to. This follows the standard
@@ -59,6 +60,7 @@ local require = require(script.Parent.loader).load(script)
59
60
 
60
61
  local Subscription = require("Subscription")
61
62
  local DuckTypeUtils = require("DuckTypeUtils")
63
+ local _MaidTaskUtils = require("MaidTaskUtils")
62
64
 
63
65
  local ENABLE_STACK_TRACING = false
64
66
 
@@ -66,12 +68,24 @@ local Observable = {}
66
68
  Observable.ClassName = "Observable"
67
69
  Observable.__index = Observable
68
70
 
71
+ export type OnSubscribe<T...> = (subscription: Subscription.Subscription<T...>) -> _MaidTaskUtils.MaidTask?
72
+
73
+ export type Transformer<T..., U...> = (observable: Observable<T...>) -> Observable<U...>
74
+
75
+ export type Observable<T...> = typeof(setmetatable(
76
+ {} :: {
77
+ _source: string?,
78
+ _onSubscribe: OnSubscribe<T...>,
79
+ },
80
+ Observable
81
+ ))
82
+
69
83
  --[=[
70
84
  Returns whether or not a value is an observable.
71
85
  @param item any
72
86
  @return boolean
73
87
  ]=]
74
- function Observable.isObservable(item)
88
+ function Observable.isObservable(item: any): boolean
75
89
  return DuckTypeUtils.isImplementation(Observable, item)
76
90
  end
77
91
 
@@ -83,7 +97,7 @@ end
83
97
  return Observable.new(function(sub)
84
98
  local maid = Maid.new()
85
99
 
86
- for _, item in pairs(parent:GetChildren()) do
100
+ for _, item in parent:GetChildren() do
87
101
  sub:Fire(item)
88
102
  end
89
103
  maid:GiveTask(parent.ChildAdded:Connect(function(child)
@@ -103,12 +117,12 @@ end
103
117
  @param onSubscribe (subscription: Subscription<T>) -> MaidTask
104
118
  @return Observable<T>
105
119
  ]=]
106
- function Observable.new(onSubscribe)
120
+ function Observable.new<T...>(onSubscribe: OnSubscribe<T...>): Observable<T...>
107
121
  assert(type(onSubscribe) == "function", "Bad onSubscribe")
108
122
 
109
123
  return setmetatable({
110
- _source = if ENABLE_STACK_TRACING then debug.traceback("Observable.new()", 2) else nil;
111
- _onSubscribe = onSubscribe;
124
+ _source = if ENABLE_STACK_TRACING then debug.traceback("Observable.new()", 2) else nil,
125
+ _onSubscribe = onSubscribe,
112
126
  }, Observable)
113
127
  end
114
128
 
@@ -132,11 +146,11 @@ end
132
146
  @param transformers { (observable: Observable<T>) -> Observable<T> }
133
147
  @return Observable<T>
134
148
  ]=]
135
- function Observable:Pipe(transformers)
149
+ function Observable.Pipe<T...>(self: Observable<T...>, transformers: { Transformer<T..., ...any> }): Observable<...any>
136
150
  assert(type(transformers) == "table", "Bad transformers")
137
151
 
138
- local current = self
139
- for _, transformer in pairs(transformers) do
152
+ local current: any = self
153
+ for _, transformer in transformers do
140
154
  assert(type(transformer) == "function", "Bad transformer")
141
155
  current = transformer(current)
142
156
  assert(Observable.isObservable(current), "Transformer must return an observable")
@@ -154,12 +168,17 @@ end
154
168
  @param completeCallback function?
155
169
  @return MaidTask
156
170
  ]=]
157
- function Observable:Subscribe(fireCallback, failCallback, completeCallback)
171
+ function Observable.Subscribe<T...>(
172
+ self: Observable<T...>,
173
+ fireCallback: Subscription.FireCallback<T...>?,
174
+ failCallback: Subscription.FailCallback?,
175
+ completeCallback: Subscription.CompleteCallback?
176
+ ): Subscription.Subscription<T...>
158
177
  local sub = Subscription.new(fireCallback, failCallback, completeCallback, self._source)
159
178
 
160
179
  sub:_assignCleanup(self._onSubscribe(sub))
161
180
 
162
- return sub
181
+ return sub :: any
163
182
  end
164
183
 
165
- return Observable
184
+ return Observable
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  This allows the storage of subscriptions for keys, such that something
3
4
  can subscribe onto a key, and events can be invoked onto keys.
@@ -7,13 +8,21 @@
7
8
  local require = require(script.Parent.loader).load(script)
8
9
 
9
10
  local Observable = require("Observable")
11
+ local _Subscription = require("Subscription")
10
12
 
11
13
  local ObservableSubscriptionTable = {}
12
14
  ObservableSubscriptionTable.ClassName = "ObservableSubscriptionTable"
13
15
  ObservableSubscriptionTable.__index = ObservableSubscriptionTable
14
16
 
15
- function ObservableSubscriptionTable.new()
16
- local self = setmetatable({}, ObservableSubscriptionTable)
17
+ export type ObservableSubscriptionTable<T...> = typeof(setmetatable(
18
+ {} :: {
19
+ _subMap: { [any]: { _Subscription.Subscription<T...> } },
20
+ },
21
+ ObservableSubscriptionTable
22
+ ))
23
+
24
+ function ObservableSubscriptionTable.new<T...>(): ObservableSubscriptionTable<T...>
25
+ local self = setmetatable({} :: any, ObservableSubscriptionTable)
17
26
 
18
27
  self._subMap = {} -- { TKey: Subscription<TEmit> }
19
28
 
@@ -25,7 +34,7 @@ end
25
34
  @param key TKey
26
35
  @param ... TEmit
27
36
  ]=]
28
- function ObservableSubscriptionTable:Fire(key, ...)
37
+ function ObservableSubscriptionTable.Fire<T...>(self: ObservableSubscriptionTable<T...>, key: any, ...)
29
38
  assert(key ~= nil, "Bad key")
30
39
 
31
40
  local subs = self._subMap[key]
@@ -34,7 +43,7 @@ function ObservableSubscriptionTable:Fire(key, ...)
34
43
  end
35
44
 
36
45
  -- Make a copy so we don't have to worry about our last changing
37
- for _, sub in pairs(table.clone(subs)) do
46
+ for _, sub: any in table.clone(subs) do
38
47
  if sub:IsPending() then
39
48
  -- TODO: Use connection here
40
49
  task.spawn(sub.Fire, sub, ...)
@@ -48,7 +57,7 @@ end
48
57
  @param key TKey
49
58
  @return boolean
50
59
  ]=]
51
- function ObservableSubscriptionTable:HasSubscriptions(key)
60
+ function ObservableSubscriptionTable.HasSubscriptions<T...>(self: ObservableSubscriptionTable<T...>, key: any): boolean
52
61
  return self._subMap[key] ~= nil
53
62
  end
54
63
 
@@ -57,7 +66,7 @@ end
57
66
 
58
67
  @param key TKey
59
68
  ]=]
60
- function ObservableSubscriptionTable:Complete(key)
69
+ function ObservableSubscriptionTable.Complete<T...>(self: ObservableSubscriptionTable<T...>, key: any)
61
70
  local subs = self._subMap[key]
62
71
  if not subs then
63
72
  return
@@ -66,7 +75,7 @@ function ObservableSubscriptionTable:Complete(key)
66
75
  local subsToComplete = table.clone(subs)
67
76
  self._subMap[key] = nil
68
77
 
69
- for _, sub in pairs(subsToComplete) do
78
+ for _, sub: any in subsToComplete do
70
79
  if sub:IsPending() then
71
80
  task.spawn(sub.Complete, sub)
72
81
  end
@@ -78,7 +87,7 @@ end
78
87
 
79
88
  @param key TKey
80
89
  ]=]
81
- function ObservableSubscriptionTable:Fail(key)
90
+ function ObservableSubscriptionTable.Fail<T...>(self: ObservableSubscriptionTable<T...>, key: any)
82
91
  local subs = self._subMap[key]
83
92
  if not subs then
84
93
  return
@@ -87,20 +96,26 @@ function ObservableSubscriptionTable:Fail(key)
87
96
  local subsToFail = table.clone(subs)
88
97
  self._subMap[key] = nil
89
98
 
90
- for _, sub in pairs(subsToFail) do
99
+ for _, sub: any in subsToFail do
91
100
  if sub:IsPending() then
92
101
  task.spawn(sub.Fail, sub)
93
102
  end
94
103
  end
95
104
  end
96
105
 
106
+ export type RetrieveInitialValue<T...> = (sub: _Subscription.Subscription<T...>) -> ()
107
+
97
108
  --[=[
98
109
  Observes for the key
99
110
  @param key TKey
100
111
  @param retrieveInitialValue callback -- Optional
101
112
  @return Observable<TEmit>
102
113
  ]=]
103
- function ObservableSubscriptionTable:Observe(key, retrieveInitialValue)
114
+ function ObservableSubscriptionTable.Observe<T...>(
115
+ self: ObservableSubscriptionTable<T...>,
116
+ key: any,
117
+ retrieveInitialValue: RetrieveInitialValue<T...>?
118
+ ): Observable.Observable<T...>
104
119
  assert(key ~= nil, "Bad key")
105
120
 
106
121
  return Observable.new(function(sub)
@@ -142,12 +157,14 @@ end
142
157
  --[=[
143
158
  Completes all subscriptions and removes them from the list.
144
159
  ]=]
145
- function ObservableSubscriptionTable:Destroy()
160
+ function ObservableSubscriptionTable.Destroy<T...>(self: ObservableSubscriptionTable<T...>)
146
161
  while next(self._subMap) do
147
162
  local key, list = next(self._subMap)
163
+ assert(key, "Key should not be nil")
164
+
148
165
  self._subMap[key] = nil
149
166
 
150
- for _, sub in pairs(list) do
167
+ for _, sub: any in list do
151
168
  if sub:IsPending() then
152
169
  task.spawn(sub.Complete, sub)
153
170
  end
package/src/Shared/Rx.lua CHANGED
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Observable rx library for Roblox by Quenty. This provides a variety of
3
4
  composition classes to be used, and is the primary entry point for an
@@ -12,14 +13,20 @@
12
13
 
13
14
  local require = require(script.Parent.loader).load(script)
14
15
 
16
+ local CancelToken = require("CancelToken")
15
17
  local Maid = require("Maid")
18
+ local MaidTaskUtils = require("MaidTaskUtils")
16
19
  local Observable = require("Observable")
17
20
  local Promise = require("Promise")
18
21
  local Symbol = require("Symbol")
19
22
  local ThrottledFunction = require("ThrottledFunction")
23
+ local _Subscription = require("Subscription")
20
24
  local cancellableDelay = require("cancellableDelay")
21
- local CancelToken = require("CancelToken")
22
- local MaidTaskUtils = require("MaidTaskUtils")
25
+ local _Signal = require("Signal")
26
+
27
+ export type Map<Key, Value> = { [Key]: Value }
28
+ export type Set<T> = { [T]: true }
29
+ export type Predicate<T...> = (T...) -> boolean
23
30
 
24
31
  local UNSET_VALUE = Symbol.named("unsetValue")
25
32
  local function identity(...)
@@ -42,8 +49,11 @@ end
42
49
  local Rx = {
43
50
  EMPTY = Observable.new(function(sub)
44
51
  sub:Complete()
52
+ return
53
+ end),
54
+ NEVER = Observable.new(function(_)
55
+ return
45
56
  end),
46
- NEVER = Observable.new(function(_) end),
47
57
  }
48
58
 
49
59
  --[=[
@@ -55,7 +65,7 @@ local Rx = {
55
65
  ]=]
56
66
  function Rx.pipe(transformers)
57
67
  assert(type(transformers) == "table", "Bad transformers")
58
- for index, transformer in pairs(transformers) do
68
+ for index, transformer in transformers do
59
69
  if type(transformer) ~= "function" then
60
70
  error(
61
71
  string.format(
@@ -71,7 +81,7 @@ function Rx.pipe(transformers)
71
81
  assert(source, "Bad source")
72
82
 
73
83
  local current = source
74
- for key, transformer in pairs(transformers) do
84
+ for key, transformer in transformers do
75
85
  current = transformer(current)
76
86
 
77
87
  if not (type(current) == "table" and current.ClassName == "Observable") then
@@ -102,7 +112,7 @@ end
102
112
  @param ... any -- Arguments to emit
103
113
  @return Observable
104
114
  ]=]
105
- function Rx.of(...)
115
+ function Rx.of<T...>(...: T...): Observable.Observable<T...>
106
116
  local args = table.pack(...)
107
117
 
108
118
  return Observable.new(function(sub)
@@ -111,6 +121,7 @@ function Rx.of(...)
111
121
  end
112
122
 
113
123
  sub:Complete()
124
+ return
114
125
  end)
115
126
  end
116
127
 
@@ -125,6 +136,7 @@ function Rx.failed(...)
125
136
 
126
137
  return Observable.new(function(sub)
127
138
  sub:Fail(table.unpack(args, 1, args.n))
139
+ return
128
140
  end)
129
141
  end
130
142
 
@@ -194,11 +206,11 @@ end
194
206
  @param observables { Observable }
195
207
  @return Observable
196
208
  ]=]
197
- function Rx.merge(observables)
209
+ function Rx.merge<T...>(observables: { Observable.Observable<T...> }): Observable.Observable<T...>
198
210
  assert(type(observables) == "table", "Bad observables")
199
211
 
200
212
  local totalCount = 0
201
- for _, item in pairs(observables) do
213
+ for _, item in observables do
202
214
  assert(Observable.isObservable(item), "Not an observable")
203
215
  totalCount = totalCount + 1
204
216
  end
@@ -207,7 +219,7 @@ function Rx.merge(observables)
207
219
  local maid = Maid.new()
208
220
  local pendingCount = totalCount
209
221
 
210
- for _, observable in pairs(observables) do
222
+ for _, observable: any in observables do
211
223
  maid:GiveTask(observable:Subscribe(function(...)
212
224
  sub:Fire(...)
213
225
  end, function(...)
@@ -233,10 +245,10 @@ end
233
245
  @param event Signal<T>
234
246
  @return Observable<T>
235
247
  ]=]
236
- function Rx.fromSignal(event)
248
+ function Rx.fromSignal<T...>(event: _Signal.Signal<T...> | RBXScriptSignal): Observable.Observable<T...>
237
249
  return Observable.new(function(sub)
238
250
  -- This stream never completes or fails!
239
- return event:Connect(function(...)
251
+ return (event :: any):Connect(function(...)
240
252
  sub:Fire(...)
241
253
  end)
242
254
  end)
@@ -249,7 +261,7 @@ end
249
261
  @param promise Promise<T>
250
262
  @return Observable<T>
251
263
  ]=]
252
- function Rx.fromPromise(promise)
264
+ function Rx.fromPromise<T...>(promise: Promise.Promise<T...>): Observable.Observable<T...>
253
265
  assert(Promise.isPromise(promise), "Bad promise")
254
266
 
255
267
  return Observable.new(function(sub)
@@ -328,7 +340,7 @@ end
328
340
  @param callback function
329
341
  @return (source: Observable) -> Observable
330
342
  ]=]
331
- function Rx.start(callback)
343
+ function Rx.start<T...>(callback: () -> T...): Observable.Transformer<T..., T...>
332
344
  return function(source)
333
345
  assert(Observable.isObservable(source), "Bad observable")
334
346
 
@@ -348,10 +360,10 @@ end
348
360
 
349
361
  @return (source: Observable) -> Observable
350
362
  ]=]
351
- function Rx.share()
352
- return function(source)
363
+ function Rx.share<T...>(): Observable.Transformer<T..., T...>
364
+ return function(source): Observable.Observable<T...>
353
365
  local shareMaid = Maid.new()
354
- local subs = {}
366
+ local subs: { _Subscription.Subscription<T...> } = {}
355
367
 
356
368
  local lastFail = UNSET_VALUE
357
369
  local lastComplete = UNSET_VALUE
@@ -362,17 +374,17 @@ function Rx.share()
362
374
  lastComplete = UNSET_VALUE
363
375
 
364
376
  shareMaid._currentSub = source:Subscribe(function(...)
365
- for _, sub in pairs(subs) do
377
+ for _, sub: any in subs do
366
378
  sub:Fire(...)
367
379
  end
368
380
  end, function(...)
369
381
  lastFail = table.pack(...)
370
- for _, sub in pairs(subs) do
382
+ for _, sub: any in subs do
371
383
  sub:Fail(...)
372
384
  end
373
385
  end, function(...)
374
386
  lastComplete = table.pack(...)
375
- for _, sub in pairs(subs) do
387
+ for _, sub: any in subs do
376
388
  sub:Complete(...)
377
389
  end
378
390
  end)
@@ -412,7 +424,7 @@ function Rx.share()
412
424
  end
413
425
  end
414
426
  end
415
- end)
427
+ end) :: any
416
428
  end
417
429
  end
418
430
 
@@ -423,27 +435,32 @@ end
423
435
  @param windowTimeSeconds number? -- Time
424
436
  @return (source: Observable) -> Observable
425
437
  ]=]
426
- function Rx.shareReplay(bufferSize: number?, windowTimeSeconds: number?)
438
+ function Rx.shareReplay<T...>(bufferSize: number?, windowTimeSeconds: number?): Observable.Transformer<T..., T...>
427
439
  assert(type(bufferSize) == "number" or bufferSize == nil, "Bad bufferSize")
428
440
  assert(type(windowTimeSeconds) == "number" or windowTimeSeconds == nil, "Bad windowTimeSeconds")
429
441
 
430
- bufferSize = bufferSize or math.huge
431
- windowTimeSeconds = windowTimeSeconds or math.huge
442
+ local maxBufferSize = bufferSize or math.huge
443
+ local windowTime = windowTimeSeconds or math.huge
432
444
 
433
445
  return function(source)
434
446
  local shareMaid = Maid.new()
435
- local subs = {}
447
+ local subs: { _Subscription.Subscription<T...> } = {}
436
448
 
437
- local buffer = {}
449
+ type Event = {
450
+ n: number,
451
+ timestamp: number,
452
+ }
453
+
454
+ local buffer: { Event } = {}
438
455
  local lastFail = UNSET_VALUE
439
456
  local lastComplete = UNSET_VALUE
440
457
 
441
- local function getEventsCopy()
458
+ local function getEventsCopy(): { Event }
442
459
  local now = os.clock()
443
460
  local events = {}
444
461
 
445
- for _, event in pairs(buffer) do
446
- if (now - event.timestamp) <= windowTimeSeconds then
462
+ for _, event in buffer do
463
+ if (now - event.timestamp) <= windowTime then
447
464
  table.insert(events, event)
448
465
  end
449
466
  end
@@ -460,17 +477,17 @@ function Rx.shareReplay(bufferSize: number?, windowTimeSeconds: number?)
460
477
  shareMaid._currentSub = source:Subscribe(function(...)
461
478
  -- TODO: also prune events by timestamp
462
479
 
463
- if #buffer + 1 > bufferSize then
480
+ if #buffer + 1 > maxBufferSize then
464
481
  table.remove(buffer, 1) -- O(n), not great.
465
482
  end
466
483
 
467
484
  -- Queue before we start
468
- local event = table.pack(...)
485
+ local event: any = table.pack(...)
469
486
  event.timestamp = os.clock()
470
487
  table.insert(buffer, event)
471
488
 
472
489
  -- Copy subs so removal doesn't affect replay
473
- for _, sub in pairs(table.clone(subs)) do
490
+ for _, sub: any in table.clone(subs) do
474
491
  if sub:IsPending() then
475
492
  sub:Fire(table.unpack(event, 1, event.n))
476
493
  end
@@ -479,7 +496,7 @@ function Rx.shareReplay(bufferSize: number?, windowTimeSeconds: number?)
479
496
  lastFail = table.pack(...)
480
497
 
481
498
  -- Copy subs so removal doesn't affect replay
482
- for _, sub in pairs(table.clone(subs)) do
499
+ for _, sub: any in table.clone(subs) do
483
500
  if sub:IsPending() then
484
501
  sub:Fail(...)
485
502
  end
@@ -488,7 +505,7 @@ function Rx.shareReplay(bufferSize: number?, windowTimeSeconds: number?)
488
505
  lastComplete = table.pack(...)
489
506
 
490
507
  -- Copy subs so removal doesn't affect replay
491
- for _, sub in pairs(table.clone(subs)) do
508
+ for _, sub: any in table.clone(subs) do
492
509
  if sub:IsPending() then
493
510
  sub:Complete(...)
494
511
  end
@@ -521,7 +538,7 @@ function Rx.shareReplay(bufferSize: number?, windowTimeSeconds: number?)
521
538
  table.insert(subs, sub)
522
539
 
523
540
  -- Firing could lead to re-entrance. Lets just use the buffer as-is.
524
- for _, item in pairs(getEventsCopy()) do
541
+ for _, item in getEventsCopy() do
525
542
  sub:Fire(table.unpack(item, 1, item.n))
526
543
  end
527
544
 
@@ -537,7 +554,7 @@ function Rx.shareReplay(bufferSize: number?, windowTimeSeconds: number?)
537
554
  end
538
555
  end
539
556
  end
540
- end)
557
+ end) :: Observable.Observable<T...>
541
558
  end
542
559
  end
543
560
 
@@ -546,7 +563,7 @@ end
546
563
 
547
564
  @return (source: Observable) -> Observable
548
565
  ]=]
549
- function Rx.cache()
566
+ function Rx.cache<T...>(): Observable.Transformer<T..., T...>
550
567
  return Rx.shareReplay(1)
551
568
  end
552
569
 
@@ -556,19 +573,19 @@ end
556
573
  @param callback () -> { T }
557
574
  @return (source: Observable) -> Observable
558
575
  ]=]
559
- function Rx.startFrom(callback)
576
+ function Rx.startFrom<T, U>(callback: () -> { U }): Observable.Transformer<(T), (U | T)>
560
577
  assert(type(callback) == "function", "Bad callback")
561
578
 
562
579
  return function(source)
563
580
  assert(Observable.isObservable(source), "Bad observable")
564
581
 
565
582
  return Observable.new(function(sub)
566
- for _, value in pairs(callback()) do
583
+ for _, value in callback() do
567
584
  sub:Fire(value)
568
585
  end
569
586
 
570
587
  return source:Subscribe(sub:GetFireFailComplete())
571
- end)
588
+ end) :: any
572
589
  end
573
590
  end
574
591
 
@@ -579,19 +596,19 @@ end
579
596
  @param values { T }
580
597
  @return (source: Observable) -> Observable
581
598
  ]=]
582
- function Rx.startWith(values)
599
+ function Rx.startWith<T, U>(values: { U }): Observable.Transformer<(T), (T | U)>
583
600
  assert(type(values) == "table", "Bad values")
584
601
 
585
602
  return function(source)
586
603
  assert(Observable.isObservable(source), "Bad observable")
587
604
 
588
605
  return Observable.new(function(sub)
589
- for _, item in pairs(values) do
606
+ for _, item in values do
590
607
  sub:Fire(item)
591
608
  end
592
609
 
593
610
  return source:Subscribe(sub:GetFireFailComplete())
594
- end)
611
+ end) :: any
595
612
  end
596
613
  end
597
614
 
@@ -604,24 +621,24 @@ end
604
621
 
605
622
  https://reactivex.io/documentation/operators/scan.html
606
623
 
607
- @param accumulator function
608
- @param seed any | nil
624
+ @param accumulator (T, U...) -> T
625
+ @param seed T?
609
626
  @return (source: Observable) -> Observable
610
627
  ]=]
611
- function Rx.scan(accumulator, seed)
628
+ function Rx.scan<T, U...>(accumulator: (T?, U...) -> T, seed: T?): Observable.Transformer<(U...), (T)>
612
629
  assert(type(accumulator) == "function", "Bad accumulator")
613
630
 
614
631
  return function(source)
615
632
  assert(Observable.isObservable(source), "Bad observable")
616
633
 
617
634
  return Observable.new(function(sub)
618
- local current = seed
635
+ local current: T? = seed
619
636
 
620
637
  return source:Subscribe(function(...)
621
638
  current = accumulator(current, ...)
622
639
  sub:Fire(current)
623
640
  end, sub:GetFailComplete())
624
- end)
641
+ end) :: any
625
642
  end
626
643
  end
627
644
 
@@ -747,12 +764,12 @@ function Rx.endWith(values)
747
764
  maid:GiveTask(source:Subscribe(function(...)
748
765
  sub:Fire(...)
749
766
  end, function(...)
750
- for _, item in pairs(values) do
767
+ for _, item in values do
751
768
  sub:Fire(item)
752
769
  end
753
770
  sub:Fail(...)
754
771
  end, function()
755
- for _, item in pairs(values) do
772
+ for _, item in values do
756
773
  sub:Fire(item)
757
774
  end
758
775
  sub:Complete()
@@ -778,10 +795,10 @@ end
778
795
  @param predicate (value: T) -> boolean
779
796
  @return (source: Observable<T>) -> Observable<T>
780
797
  ]=]
781
- function Rx.where(predicate)
798
+ function Rx.where<T...>(predicate: Predicate<T...>): Observable.Transformer<T..., T...>
782
799
  assert(type(predicate) == "function", "Bad predicate callback")
783
800
 
784
- return function(source)
801
+ return function(source: Observable.Observable<T...>): Observable.Observable<T...>
785
802
  assert(Observable.isObservable(source), "Bad observable")
786
803
 
787
804
  return Observable.new(function(sub)
@@ -806,7 +823,7 @@ end
806
823
  ```
807
824
  @return (source: Observable<T>) -> Observable<T>
808
825
  ]=]
809
- function Rx.distinct()
826
+ function Rx.distinct<T...>(): Observable.Transformer<T..., T...>
810
827
  return function(source)
811
828
  assert(Observable.isObservable(source), "Bad observable")
812
829
 
@@ -822,7 +839,7 @@ function Rx.distinct()
822
839
  last = value
823
840
  sub:Fire(last)
824
841
  end, sub:GetFailComplete())
825
- end)
842
+ end) :: Observable.Observable<T...>
826
843
  end
827
844
  end
828
845
 
@@ -860,7 +877,7 @@ end
860
877
  @param project (T) -> U
861
878
  @return (source: Observable<T>) -> Observable<U>
862
879
  ]=]
863
- function Rx.map(project)
880
+ function Rx.map<T..., U...>(project: (T...) -> U...): Observable.Transformer<T..., U...>
864
881
  assert(type(project) == "function", "Bad project callback")
865
882
 
866
883
  return function(source)
@@ -870,7 +887,7 @@ function Rx.map(project)
870
887
  return source:Subscribe(function(...)
871
888
  sub:Fire(project(...))
872
889
  end, sub:GetFailComplete())
873
- end)
890
+ end) :: Observable.Observable<U...>
874
891
  end
875
892
  end
876
893
 
@@ -891,7 +908,7 @@ end
891
908
 
892
909
  @return (source: Observable<Observable<T>>) -> Observable<T>
893
910
  ]=]
894
- function Rx.mergeAll()
911
+ function Rx.mergeAll<T...>(): Observable.Transformer<Observable.Observable<T...>, T...>
895
912
  return Rx.flatMap(identity)
896
913
  end
897
914
 
@@ -906,7 +923,7 @@ end
906
923
 
907
924
  @return (source: Observable<Observable<T>>) -> Observable<T>
908
925
  ]=]
909
- function Rx.switchAll()
926
+ function Rx.switchAll<T...>(): Observable.Transformer<Observable.Observable<T...>, T...>
910
927
  return Rx.switchMap(identity)
911
928
  end
912
929
 
@@ -918,16 +935,16 @@ end
918
935
  @param project (value: T) -> Observable<U>
919
936
  @return (source: Observable<T>) -> Observable<U>
920
937
  ]=]
921
- function Rx.flatMap(project)
938
+ function Rx.flatMap<T..., U...>(project: (T...) -> Observable.Observable<U...>): Observable.Transformer<(T...), (U...)>
922
939
  assert(type(project) == "function", "Bad project")
923
940
 
924
- return function(source)
941
+ return function(source: Observable.Observable<T...>): Observable.Observable<U...>
925
942
  assert(Observable.isObservable(source), "Bad observable")
926
943
 
927
- return Observable.new(function(sub)
928
- local isComplete = false
929
- local pendingCount = 0
930
- local subscriptions = {}
944
+ return Observable.new(function(sub: _Subscription.Subscription<U...>)
945
+ local isComplete: boolean = false
946
+ local pendingCount: number = 0
947
+ local subscriptions: Set<_Subscription.Subscription<U...>> = {}
931
948
 
932
949
  local function checkComplete()
933
950
  if isComplete and pendingCount == 0 then
@@ -935,8 +952,8 @@ function Rx.flatMap(project)
935
952
  end
936
953
  end
937
954
 
938
- local function onNextObservable(...)
939
- local observable = project(...)
955
+ local function onNextObservable(...: T...)
956
+ local observable: Observable.Observable<U...> = project(...)
940
957
  assert(Observable.isObservable(observable), "Bad observable returned from subscription project call")
941
958
 
942
959
  if not sub:IsPending() then
@@ -945,9 +962,9 @@ function Rx.flatMap(project)
945
962
  end
946
963
 
947
964
  local innerCompleteOrFail = false
948
- local subscription
965
+ local subscription: _Subscription.Subscription<U...>? = nil
949
966
 
950
- local function onNext(...)
967
+ local function onNext(...: U...)
951
968
  if innerCompleteOrFail or pendingCount == 0 then
952
969
  return
953
970
  end
@@ -988,15 +1005,16 @@ function Rx.flatMap(project)
988
1005
  end
989
1006
 
990
1007
  pendingCount += 1
991
- subscription = observable:Subscribe(onNext, onFail, onComplete)
1008
+ local newSub = observable:Subscribe(onNext, onFail, onComplete)
1009
+ subscription = newSub
992
1010
 
993
1011
  if innerCompleteOrFail or not sub:IsPending() then
994
1012
  -- Subscribing cancelled ourselves in some way
995
- subscription:Destroy()
1013
+ newSub:Destroy()
996
1014
  return
997
1015
  end
998
1016
 
999
- subscriptions[subscription] = true
1017
+ subscriptions[newSub] = true
1000
1018
  end
1001
1019
 
1002
1020
  local outerSubscription = source:Subscribe(onNextObservable, function(...)
@@ -1009,13 +1027,13 @@ function Rx.flatMap(project)
1009
1027
  return function()
1010
1028
  pendingCount = 0
1011
1029
 
1012
- for subscription, _ in pairs(subscriptions) do
1030
+ for subscription: any in subscriptions do
1013
1031
  subscription:Destroy()
1014
1032
  end
1015
1033
 
1016
1034
  outerSubscription:Destroy()
1017
1035
  end
1018
- end)
1036
+ end) :: any
1019
1037
  end
1020
1038
  end
1021
1039
 
@@ -1075,17 +1093,17 @@ end
1075
1093
  @param project function
1076
1094
  @return Observable
1077
1095
  ]=]
1078
- function Rx.switchMap(project)
1096
+ function Rx.switchMap<T..., U...>(project: (T...) -> Observable.Observable<U...>): Observable.Transformer<(T...), (U...)>
1079
1097
  assert(type(project) == "function", "Bad project")
1080
1098
 
1081
- return function(source)
1099
+ return function(source: Observable.Observable<T...>)
1082
1100
  assert(Observable.isObservable(source), "Bad observable")
1083
1101
 
1084
- return Observable.new(function(sub)
1085
- local isComplete = false
1086
- local insideComplete = false
1087
- local insideSubscription = nil
1088
- local outerIndex = 0
1102
+ return Observable.new(function(sub: _Subscription.Subscription<U...>)
1103
+ local isComplete: boolean = false
1104
+ local insideComplete: boolean = false
1105
+ local insideSubscription: _Subscription.Subscription<T...>? = nil
1106
+ local outerIndex: number? = 0
1089
1107
 
1090
1108
  local function checkComplete()
1091
1109
  if isComplete and insideComplete then
@@ -1097,7 +1115,7 @@ function Rx.switchMap(project)
1097
1115
  local function onNextObservable(...)
1098
1116
  insideComplete = false
1099
1117
 
1100
- local observable = project(...)
1118
+ local observable: Observable.Observable<U...> = project(...)
1101
1119
  assert(Observable.isObservable(observable), "Bad observable returned from subscription project call")
1102
1120
 
1103
1121
  -- Handle cancellation when external callers do weird state stuff
@@ -1119,7 +1137,7 @@ function Rx.switchMap(project)
1119
1137
  return
1120
1138
  end
1121
1139
 
1122
- local function onNext(...)
1140
+ local function onNext(...: U...)
1123
1141
  if index ~= outerIndex then
1124
1142
  return
1125
1143
  end
@@ -1155,7 +1173,7 @@ function Rx.switchMap(project)
1155
1173
  return
1156
1174
  end
1157
1175
 
1158
- insideSubscription = subscription
1176
+ insideSubscription = subscription :: any
1159
1177
  end
1160
1178
 
1161
1179
  local outerSubscription = source:Subscribe(onNextObservable, function(...)
@@ -1176,7 +1194,7 @@ function Rx.switchMap(project)
1176
1194
 
1177
1195
  outerSubscription:Destroy()
1178
1196
  end
1179
- end)
1197
+ end) :: Observable.Observable<U...>
1180
1198
  end
1181
1199
  end
1182
1200
 
@@ -1226,13 +1244,14 @@ end
1226
1244
  @param ... any
1227
1245
  @return Observable
1228
1246
  ]=]
1229
- function Rx.packed(...)
1247
+ function Rx.packed<T...>(...: T...): Observable.Observable<T...>
1230
1248
  local args = table.pack(...)
1231
1249
 
1232
1250
  return Observable.new(function(sub)
1233
1251
  sub:Fire(unpack(args, 1, args.n))
1234
1252
  sub:Complete()
1235
- end)
1253
+ return
1254
+ end) :: any
1236
1255
  end
1237
1256
 
1238
1257
  --[=[
@@ -1419,20 +1438,20 @@ end
1419
1438
  @param observables { [TKey]: Observable<TEmitted> | TEmitted }
1420
1439
  @return Observable<{ [TKey]: TEmitted }>
1421
1440
  ]=]
1422
- function Rx.combineLatest(observables)
1441
+ function Rx.combineLatest<K, V>(observables: Map<K, Observable.Observable<V> | V>): Observable.Observable<Map<K, V>>
1423
1442
  assert(type(observables) == "table", "Bad observables")
1424
1443
 
1425
1444
  return Observable.new(function(sub)
1426
1445
  local unset = 0
1427
- local latest = {}
1446
+ local latest: Map<K, V> = {}
1428
1447
 
1429
1448
  -- Instead of caching this, use extra compute here
1430
- for key, value in pairs(observables) do
1449
+ for key, value in observables do
1431
1450
  if Observable.isObservable(value) then
1432
1451
  unset += 1
1433
1452
  latest[key] = UNSET_VALUE
1434
1453
  else
1435
- latest[key] = value
1454
+ latest[key] = value :: V
1436
1455
  end
1437
1456
  end
1438
1457
 
@@ -1447,19 +1466,19 @@ function Rx.combineLatest(observables)
1447
1466
 
1448
1467
  local function failOnFirst(...)
1449
1468
  pending -= 1
1450
- latest = nil
1469
+ latest = nil :: any
1451
1470
  sub:Fail(...)
1452
1471
  end
1453
1472
 
1454
1473
  local function completeOnAllPendingDone()
1455
1474
  pending -= 1
1456
1475
  if pending == 0 then
1457
- latest = nil
1476
+ latest = nil :: any
1458
1477
  sub:Complete()
1459
1478
  end
1460
1479
  end
1461
1480
 
1462
- for key, observer in pairs(observables) do
1481
+ for key, observer: any in observables do
1463
1482
  if not Observable.isObservable(observer) then
1464
1483
  continue
1465
1484
  end
@@ -1478,7 +1497,7 @@ function Rx.combineLatest(observables)
1478
1497
  end
1479
1498
 
1480
1499
  return maid
1481
- end)
1500
+ end) :: any
1482
1501
  end
1483
1502
 
1484
1503
  --[=[
@@ -1495,10 +1514,10 @@ function Rx.combineLatestDefer(observables)
1495
1514
  return Observable.new(function(sub)
1496
1515
  local pending = 0
1497
1516
  local unset = 0
1498
- local latest = {}
1517
+ local latest: any = {}
1499
1518
 
1500
1519
  -- Instead of caching this, use extra compute here
1501
- for key, value in pairs(observables) do
1520
+ for key, value in observables do
1502
1521
  if Observable.isObservable(value) then
1503
1522
  pending += 1
1504
1523
  unset += 1
@@ -1530,14 +1549,14 @@ function Rx.combineLatestDefer(observables)
1530
1549
  end
1531
1550
  end
1532
1551
 
1533
- local queueThread = nil
1552
+ local queueThread: thread? = nil
1534
1553
  maid:GiveTask(function()
1535
1554
  if queueThread then
1536
1555
  MaidTaskUtils.doTask(queueThread)
1537
1556
  end
1538
1557
  end)
1539
1558
 
1540
- for key, observer in pairs(observables) do
1559
+ for key, observer in observables do
1541
1560
  if not Observable.isObservable(observer) then
1542
1561
  continue
1543
1562
  end
@@ -1614,7 +1633,7 @@ end
1614
1633
  @param number number
1615
1634
  @return (source: Observable<T>) -> Observable<T>
1616
1635
  ]=]
1617
- function Rx.take(number: number)
1636
+ function Rx.take<T...>(number: number): Observable.Transformer<T..., T...>
1618
1637
  assert(type(number) == "number", "Bad number")
1619
1638
  assert(number > 0, "Bad number")
1620
1639
 
@@ -1643,7 +1662,7 @@ function Rx.take(number: number)
1643
1662
  end, sub:GetFailComplete())
1644
1663
 
1645
1664
  return maid
1646
- end)
1665
+ end) :: Observable.Observable<T...>
1647
1666
  end
1648
1667
  end
1649
1668
 
@@ -1654,7 +1673,7 @@ end
1654
1673
  @param toSkip number
1655
1674
  @return (source: Observable<T>) -> Observable<T>
1656
1675
  ]=]
1657
- function Rx.skip(toSkip: number)
1676
+ function Rx.skip<T...>(toSkip: number): Observable.Transformer<T..., T...>
1658
1677
  assert(type(toSkip) == "number", "Bad toSkip")
1659
1678
  assert(toSkip > 0, "Bad toSkip")
1660
1679
 
@@ -1675,7 +1694,7 @@ function Rx.skip(toSkip: number)
1675
1694
  end, sub:GetFailComplete()))
1676
1695
 
1677
1696
  return maid
1678
- end)
1697
+ end) :: Observable.Observable<T...>
1679
1698
  end
1680
1699
  end
1681
1700
 
@@ -1689,7 +1708,7 @@ end
1689
1708
  @param observableFactory () -> Observable<T>
1690
1709
  @return Observable<T>
1691
1710
  ]=]
1692
- function Rx.defer(observableFactory)
1711
+ function Rx.defer<T>(observableFactory: () -> Observable.Observable<T>): Observable.Observable<T>
1693
1712
  return Observable.new(function(sub)
1694
1713
  local observable
1695
1714
  local ok, err = pcall(function()
@@ -1707,7 +1726,7 @@ function Rx.defer(observableFactory)
1707
1726
  end
1708
1727
 
1709
1728
  return observable:Subscribe(sub:GetFireFailComplete())
1710
- end)
1729
+ end) :: any
1711
1730
  end
1712
1731
 
1713
1732
  --[=[
@@ -1716,13 +1735,13 @@ end
1716
1735
  @param seconds number
1717
1736
  @return (source: Observable<T>) -> Observable<T>
1718
1737
  ]=]
1719
- function Rx.delay(seconds: number)
1738
+ function Rx.delay<T...>(seconds: number): Observable.Transformer<T..., T...>
1720
1739
  assert(type(seconds) == "number", "Bad seconds")
1721
1740
 
1722
1741
  return function(source)
1723
1742
  assert(Observable.isObservable(source), "Bad observable")
1724
1743
 
1725
- return Observable.new(function(sub)
1744
+ return Observable.new(function(sub: _Subscription.Subscription<T...>)
1726
1745
  local maid = Maid.new()
1727
1746
 
1728
1747
  maid:GiveTask(source:Subscribe(function(...)
@@ -1735,7 +1754,7 @@ function Rx.delay(seconds: number)
1735
1754
  end, sub:GetFailComplete()))
1736
1755
 
1737
1756
  return maid
1738
- end)
1757
+ end) :: Observable.Observable<T...>
1739
1758
  end
1740
1759
  end
1741
1760
 
@@ -1811,7 +1830,7 @@ end
1811
1830
  function Rx.withLatestFrom(inputObservables)
1812
1831
  assert(inputObservables, "Bad inputObservables")
1813
1832
 
1814
- for _, observable in pairs(inputObservables) do
1833
+ for _, observable in inputObservables do
1815
1834
  assert(Observable.isObservable(observable), "Bad observable")
1816
1835
  end
1817
1836
 
@@ -1823,7 +1842,7 @@ function Rx.withLatestFrom(inputObservables)
1823
1842
 
1824
1843
  local latest = {}
1825
1844
 
1826
- for key, observable in pairs(inputObservables) do
1845
+ for key, observable in inputObservables do
1827
1846
  latest[key] = UNSET_VALUE
1828
1847
 
1829
1848
  maid:GiveTask(observable:Subscribe(function(value)
@@ -1832,7 +1851,7 @@ function Rx.withLatestFrom(inputObservables)
1832
1851
  end
1833
1852
 
1834
1853
  maid:GiveTask(source:Subscribe(function(value)
1835
- for _, item in pairs(latest) do
1854
+ for _, item in latest do
1836
1855
  if item == UNSET_VALUE then
1837
1856
  return
1838
1857
  end
@@ -1859,7 +1878,7 @@ end
1859
1878
  @param throttleConfig { leading = true; trailing = true; }
1860
1879
  @return (source: Observable) -> Observable
1861
1880
  ]=]
1862
- function Rx.throttleTime(duration: number, throttleConfig)
1881
+ function Rx.throttleTime(duration: number, throttleConfig: ThrottledFunction.ThrottleConfig)
1863
1882
  assert(type(duration) == "number", "Bad duration")
1864
1883
  assert(type(throttleConfig) == "table" or throttleConfig == nil, "Bad throttleConfig")
1865
1884
 
@@ -1920,8 +1939,8 @@ function Rx.throttleDefer()
1920
1939
  assert(Observable.isObservable(source), "Bad observable")
1921
1940
 
1922
1941
  return Observable.new(function(sub)
1923
- local lastResult = nil
1924
- local currentQueue = nil
1942
+ local lastResult: any = nil
1943
+ local currentQueue: thread? = nil
1925
1944
 
1926
1945
  local sourceSub = source:Subscribe(function(...)
1927
1946
  if lastResult then
@@ -1972,7 +1991,7 @@ function Rx.throttle(durationSelector)
1972
1991
  return Observable.new(function(sub)
1973
1992
  local topMaid = Maid.new()
1974
1993
 
1975
- local lastResult
1994
+ local lastResult: any
1976
1995
 
1977
1996
  topMaid:GiveTask(source:Subscribe(function(...)
1978
1997
  if not lastResult then
@@ -2115,7 +2134,7 @@ function Rx.switchScan(accumulator, seed)
2115
2134
  assert(type(accumulator) == "function", "Bad accumulator")
2116
2135
 
2117
2136
  return Rx.pipe({
2118
- Rx.scan(accumulator, seed),
2137
+ Rx.scan(accumulator, seed) :: any,
2119
2138
  Rx.switchAll(),
2120
2139
  })
2121
2140
  end
@@ -2134,7 +2153,7 @@ function Rx.mergeScan(accumulator, seed)
2134
2153
  assert(type(accumulator) == "function", "Bad accumulator")
2135
2154
 
2136
2155
  return Rx.pipe({
2137
- Rx.scan(accumulator, seed),
2156
+ Rx.scan(accumulator, seed) :: any,
2138
2157
  Rx.mergeAll(),
2139
2158
  })
2140
2159
  end
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Subscriptions are used in the callback for an [Observable](/api/Observable). Standard usage
3
4
  is as follows.
@@ -24,13 +25,40 @@ local Subscription = {}
24
25
  Subscription.ClassName = "Subscription"
25
26
  Subscription.__index = Subscription
26
27
 
27
- local SubscriptionStateTypes = {
28
- PENDING = "pending";
29
- FAILED = "failed";
30
- COMPLETE = "complete";
31
- CANCELLED = "cancelled";
28
+ export type SubscriptionState = "pending" | "failed" | "complete" | "cancelled"
29
+
30
+ export type FireCallback<T...> = (T...) -> ()
31
+ export type CompleteCallback = () -> ()
32
+ export type FailCallback = (...any) -> ()
33
+
34
+ export type Subscription<T...> = typeof(setmetatable(
35
+ {} :: {
36
+ _state: SubscriptionState,
37
+ _cleanupTask: MaidTaskUtils.MaidTask?,
38
+ _fireCallback: FireCallback<T...>?,
39
+ _failCallback: FailCallback?,
40
+ _completeCallback: CompleteCallback?,
41
+ _fireCountAfterDeath: number?,
42
+ _source: string?,
43
+ _observableSource: string?,
44
+ },
45
+ Subscription
46
+ ))
47
+
48
+ export type SubscriptionStateTypes = {
49
+ PENDING: "pending",
50
+ FAILED: "failed",
51
+ COMPLETE: "complete",
52
+ CANCELLED: "cancelled",
32
53
  }
33
54
 
55
+ local SubscriptionStateTypes: SubscriptionStateTypes = table.freeze({
56
+ PENDING = "pending",
57
+ FAILED = "failed",
58
+ COMPLETE = "complete",
59
+ CANCELLED = "cancelled",
60
+ } :: SubscriptionStateTypes)
61
+
34
62
  --[=[
35
63
  Constructs a new Subscription
36
64
 
@@ -40,18 +68,23 @@ local SubscriptionStateTypes = {
40
68
  @param observableSource string?
41
69
  @return Subscription
42
70
  ]=]
43
- function Subscription.new(fireCallback, failCallback, completeCallback, observableSource)
71
+ function Subscription.new<T...>(
72
+ fireCallback: FireCallback<T...>?,
73
+ failCallback: FailCallback?,
74
+ completeCallback: CompleteCallback?,
75
+ observableSource
76
+ ): Subscription<T...>
44
77
  assert(type(fireCallback) == "function" or fireCallback == nil, "Bad fireCallback")
45
78
  assert(type(failCallback) == "function" or failCallback == nil, "Bad failCallback")
46
79
  assert(type(completeCallback) == "function" or completeCallback == nil, "Bad completeCallback")
47
80
 
48
81
  return setmetatable({
49
- _state = SubscriptionStateTypes.PENDING;
50
- _source = if ENABLE_STACK_TRACING then debug.traceback("Subscription.new()", 3) else nil;
51
- _observableSource = observableSource;
52
- _fireCallback = fireCallback;
53
- _failCallback = failCallback;
54
- _completeCallback = completeCallback;
82
+ _state = SubscriptionStateTypes.PENDING,
83
+ _source = if ENABLE_STACK_TRACING then debug.traceback("Subscription.new()", 3) else nil,
84
+ _observableSource = observableSource,
85
+ _fireCallback = fireCallback,
86
+ _failCallback = failCallback,
87
+ _completeCallback = completeCallback,
55
88
  }, Subscription)
56
89
  end
57
90
 
@@ -60,7 +93,7 @@ end
60
93
 
61
94
  @param ... any
62
95
  ]=]
63
- function Subscription:Fire(...)
96
+ function Subscription.Fire<T...>(self: Subscription<T...>, ...: T...)
64
97
  if self._state == SubscriptionStateTypes.PENDING then
65
98
  if self._fireCallback then
66
99
  self._fireCallback(...)
@@ -73,7 +106,16 @@ function Subscription:Fire(...)
73
106
  end
74
107
 
75
108
  if self._fireCountAfterDeath > 1 then
76
- warn(debug.traceback(string.format("Subscription:Fire(%s) called %d times after death. Be sure to disconnect all events.", tostring(...), self._fireCountAfterDeath), 2))
109
+ warn(
110
+ debug.traceback(
111
+ string.format(
112
+ "Subscription:Fire(%s) called %d times after death. Be sure to disconnect all events.",
113
+ (tostring :: any)(...),
114
+ self._fireCountAfterDeath or -1
115
+ ),
116
+ 2
117
+ )
118
+ )
77
119
 
78
120
  if ENABLE_STACK_TRACING then
79
121
  print(self._observableSource)
@@ -87,7 +129,7 @@ end
87
129
  Fails the subscription, preventing anything else from emitting.
88
130
  @param ... any
89
131
  ]=]
90
- function Subscription:Fail(...)
132
+ function Subscription.Fail<T...>(self: Subscription<T...>, ...: any)
91
133
  if self._state ~= SubscriptionStateTypes.PENDING then
92
134
  return
93
135
  end
@@ -101,7 +143,6 @@ function Subscription:Fail(...)
101
143
  self:_doCleanup()
102
144
  end
103
145
 
104
-
105
146
  --[=[
106
147
  Returns a tuple of fire, fail and complete functions which
107
148
  can be chained into the the next subscription.
@@ -120,8 +161,10 @@ end
120
161
  @return function
121
162
  @return function
122
163
  ]=]
123
- function Subscription:GetFireFailComplete()
124
- return function(...)
164
+ function Subscription.GetFireFailComplete<T...>(
165
+ self: Subscription<T...>
166
+ ): (FireCallback<T...>, FailCallback, CompleteCallback)
167
+ return function(...: T...)
125
168
  self:Fire(...)
126
169
  end, function(...)
127
170
  self:Fail(...)
@@ -147,7 +190,7 @@ end
147
190
  @return function
148
191
  @return function
149
192
  ]=]
150
- function Subscription:GetFailComplete()
193
+ function Subscription.GetFailComplete<T...>(self: Subscription<T...>): (FailCallback, CompleteCallback)
151
194
  return function(...)
152
195
  self:Fail(...)
153
196
  end, function(...)
@@ -161,7 +204,7 @@ end
161
204
 
162
205
  @param ... any
163
206
  ]=]
164
- function Subscription:Complete(...)
207
+ function Subscription.Complete<T...>(self: Subscription<T...>, ...)
165
208
  if self._state ~= SubscriptionStateTypes.PENDING then
166
209
  return
167
210
  end
@@ -178,11 +221,11 @@ end
178
221
  Returns whether the subscription is pending.
179
222
  @return boolean
180
223
  ]=]
181
- function Subscription:IsPending()
224
+ function Subscription.IsPending<T...>(self: Subscription<T...>): boolean
182
225
  return self._state == SubscriptionStateTypes.PENDING
183
226
  end
184
227
 
185
- function Subscription:_assignCleanup(cleanupTask)
228
+ function Subscription._assignCleanup<T...>(self: Subscription<T...>, cleanupTask: MaidTaskUtils.MaidTask?)
186
229
  assert(self._cleanupTask == nil, "Already have _cleanupTask")
187
230
 
188
231
  if MaidTaskUtils.isValidTask(cleanupTask) then
@@ -197,7 +240,7 @@ function Subscription:_assignCleanup(cleanupTask)
197
240
  end
198
241
  end
199
242
 
200
- function Subscription:_doCleanup()
243
+ function Subscription._doCleanup<T...>(self: Subscription<T...>)
201
244
  local cleanupTask = self._cleanupTask
202
245
  if cleanupTask then
203
246
  self._cleanupTask = nil
@@ -221,7 +264,7 @@ end
221
264
  be called within the usage of a subscription.
222
265
  :::
223
266
  ]=]
224
- function Subscription:Destroy()
267
+ function Subscription.Destroy<T...>(self: Subscription<T...>)
225
268
  if self._state == SubscriptionStateTypes.PENDING then
226
269
  self._state = SubscriptionStateTypes.CANCELLED
227
270
  end
@@ -231,9 +274,10 @@ end
231
274
 
232
275
  --[=[
233
276
  Alias for [Subscription.Destroy].
277
+
278
+ @method Disconnect
279
+ @within Subscription
234
280
  ]=]
235
- function Subscription:Disconnect()
236
- self:Destroy()
237
- end
281
+ Subscription.Disconnect = Subscription.Destroy
238
282
 
239
283
  return Subscription