@rbxts/evxryy-option 1.2.3 → 1.2.4

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.
Files changed (2) hide show
  1. package/out/init.luau +355 -2
  2. package/package.json +4 -1
package/out/init.luau CHANGED
@@ -1,2 +1,355 @@
1
- -- Compiled with roblox-ts v3.0.0
2
- return Option
1
+ --[[
2
+ author : evxry_ll
3
+
4
+ This module implements the Option type pattern, similar to Rust's Option<T>.
5
+ It provides a way to handle nullable values in a type-safe manner.
6
+
7
+ Option<T> can be either:
8
+ - Some(value): Contains a value of type T
9
+ - None: Contains no value
10
+ ]]
11
+
12
+ -- Type aliases for better readability
13
+ type Some<T> = T
14
+ type SomeCallback<T,K> = (T) -> K
15
+ type None<T,K> = () -> K
16
+
17
+ -- Callback type definitions used throughout the module
18
+ type Callback<T> = () -> T -- Function that returns a value of type T
19
+ type FilterCallback<T> = (value : T) -> boolean -- Function that tests if a value meets criteria
20
+ type AndThenCallback<T, K> = (value : T) -> any -- Function that chains operations
21
+
22
+ -- Constructor table for creating Option instances
23
+ local OptionConstructor = {}
24
+ OptionConstructor.__index = OptionConstructor
25
+
26
+ -- Component table containing all Option methods
27
+ local OptionComponent = {}
28
+ OptionComponent.__index = OptionComponent
29
+
30
+ -- Export type definition for Option<T>
31
+ -- An Option can have either a "Some" tag with a value, or a "None" tag with nil
32
+ export type OptionComponent<T> = typeof(setmetatable({} :: {
33
+ Tag : "Some" | "None",
34
+ Some : T,
35
+ None : nil,
36
+ },OptionComponent))
37
+
38
+ --[[
39
+ Creates a Some variant of Option containing a value
40
+ @param SomeOption The value to wrap in Some
41
+ @return An Option containing the provided value
42
+ ]]
43
+ function OptionConstructor.Some<SomeType>(SomeOption : Some<SomeType>) : OptionComponent<SomeType>
44
+ local self = setmetatable({
45
+ Some = SomeOption,
46
+ Tag = "Some",
47
+ },OptionComponent)
48
+ return self
49
+ end
50
+
51
+ --[[
52
+ Creates a None variant of Option containing no value
53
+ @return An empty Option
54
+ ]]
55
+ function OptionConstructor.None() : OptionComponent<nil>
56
+ local self = setmetatable({
57
+ None = true,
58
+ Tag = "None"
59
+ },OptionComponent)
60
+ return self
61
+ end
62
+
63
+ --[[
64
+ Checks if a value is a valid Option instance
65
+ @param option The value to check
66
+ @return true if the value is an Option, false otherwise
67
+ ]]
68
+ function OptionConstructor.IsOption<T>(option : OptionComponent<T>?)
69
+ if(option and option.Tag) then
70
+ return true
71
+ else
72
+ return false
73
+ end
74
+ end
75
+
76
+ --[[
77
+ Wraps a nullable value in an Option
78
+ If the value is nil, returns None; otherwise returns Some(value)
79
+ @param value The nullable value to wrap
80
+ @return Option<T> or Option<nil>
81
+ ]]
82
+ function OptionConstructor.Wrap<T>(value : T?)
83
+ if(value ~= nil) then
84
+ return OptionConstructor.Some(value :: T) :: OptionComponent<T>
85
+ else
86
+ return OptionConstructor.None() :: OptionComponent<nil>
87
+ end
88
+ end
89
+
90
+ --[[
91
+ Deserializes data back into an Option
92
+ Used to reconstruct Options from stored/transmitted data
93
+ @param data Serialized Option data with Tag and Value fields
94
+ @return The reconstructed Option
95
+ ]]
96
+ function OptionConstructor.Deserialize<T>(data : {Tag : "Some" | "None",Value : T})
97
+ return data.Value == nil and OptionConstructor.None() or OptionConstructor.Some(data.Value)
98
+ end
99
+
100
+ --[[
101
+ Checks if this Option contains a value (is Some variant)
102
+ @return true if Option contains a value, false if None
103
+ ]]
104
+ function OptionComponent.IsSome<T>(self : OptionComponent<T>)
105
+ return self.Tag == "Some" or self.Some ~= nil
106
+ end
107
+
108
+ --[[
109
+ Checks if this Option is empty (is None variant)
110
+ @return true if Option is None, false if it contains a value
111
+ ]]
112
+ function OptionComponent.IsNone<T>(self : OptionComponent<T>)
113
+ return self.Tag == "None" or self.None ~= nil
114
+ end
115
+
116
+ --[[
117
+ Pattern matching for Option - executes different code based on variant
118
+ @param Options Table with Some and None callbacks
119
+ @return Result of the executed callback
120
+ ]]
121
+ function OptionComponent.Match<T,K>(self : OptionComponent<T>,Options : {Some : SomeCallback<T,K>,None : None<T,K>}) : K
122
+ if(self:IsNone()) then
123
+ return Options.None() :: K
124
+ else
125
+ return Options.Some(self.Some) :: K
126
+ end
127
+ end
128
+
129
+ --[[
130
+ Asserts that the Option contains a value, throwing error if None
131
+ @param error_message Custom error message to display if assertion fails
132
+ ]]
133
+ function OptionComponent.Assert<T>(self : OptionComponent<T>,error_message : string)
134
+ assert(self:IsSome(),error_message)
135
+ end
136
+
137
+ --[[
138
+ Returns the contained value or a default if None
139
+ @param value Default value to return if Option is None
140
+ @return The contained value or the default
141
+ ]]
142
+ function OptionComponent.GetOr<T, K>(self : OptionComponent<T>,value : K) : T | K
143
+ if(self:IsSome()) then
144
+ return self.Some :: T
145
+ else
146
+ return value
147
+ end
148
+ end
149
+
150
+ --[[
151
+ Transforms the contained value using a callback function
152
+ If None, returns None without calling the callback
153
+ @param callback Function to transform the value
154
+ @return New Option with transformed value or None
155
+ ]]
156
+ function OptionComponent.Map<T,K>(self : OptionComponent<T>,callback : (value : T) -> K)
157
+ if(self:IsSome()) then
158
+ local outOption = callback(self.Some :: T)
159
+ return OptionConstructor.Some(outOption :: K) :: OptionComponent<K>
160
+ else
161
+ return OptionConstructor.None()
162
+ end
163
+ end
164
+
165
+ --[[
166
+ Filters the Option based on a predicate function
167
+ Returns None if the predicate returns false or if already None
168
+ @param callback Predicate function to test the value
169
+ @return Self if predicate passes, None otherwise
170
+ ]]
171
+ function OptionComponent.Filter<T>(self : OptionComponent<T>,callback : FilterCallback<T>)
172
+ if(self:IsSome() and callback(self.Some :: T)) then
173
+ return self
174
+ else
175
+ return OptionConstructor.None()
176
+ end
177
+ end
178
+
179
+ --[[
180
+ Returns the contained value or computes a default using a callback
181
+ @param callback Function to compute default value if None
182
+ @return The contained value or computed default
183
+ ]]
184
+ function OptionComponent.GetOrElse<T, K>(self : OptionComponent<T>,callback : Callback<K>) : T | K
185
+ if(self:IsSome()) then
186
+ return self.Some :: T
187
+ else
188
+ return callback() :: K
189
+ end
190
+ end
191
+
192
+ --[[
193
+ Exclusive OR operation between two Options
194
+ Returns Some if exactly one Option is Some, None if both are Some or both are None
195
+ @param OptionB The other Option to XOR with
196
+ @return Result of XOR operation
197
+ ]]
198
+ function OptionComponent.XOR<T,K>(self : OptionComponent<T>,OptionB : OptionComponent<K>) : OptionComponent<T | K | nil>
199
+ local ValidOptionB = OptionConstructor.IsOption(OptionB)
200
+ if(not ValidOptionB) then return self :: OptionComponent<T> end
201
+ if(self:IsSome() and OptionB:IsSome()) then
202
+ return OptionConstructor.None() :: OptionComponent<nil>
203
+ elseif(self:IsSome()) then
204
+ return self :: OptionComponent<T>
205
+ else
206
+ return OptionB :: OptionComponent<K>
207
+ end
208
+ end
209
+
210
+ --[[
211
+ Chains Option operations - applies callback only if Some
212
+ The callback must return another Option
213
+ @param callback Function that takes the value and returns an Option
214
+ @return Result of the callback or None
215
+ ]]
216
+ function OptionComponent.AndThen<T, K>(self : OptionComponent<T>,callback : (value : T) -> OptionComponent<K>)
217
+ if(self:IsSome()) then
218
+ local outOption = callback(self.Some :: T)
219
+ assert(OptionConstructor.IsOption(outOption),"current callback must return a OptionComponent.")
220
+ return outOption :: OptionComponent<K>
221
+ else
222
+ return OptionConstructor.None()
223
+ end
224
+ end
225
+
226
+ --[[
227
+ Unwraps the value with a custom panic message if None
228
+ @param msg Error message to display if Option is None
229
+ @return The contained value
230
+ @error Throws if Option is None
231
+ ]]
232
+ function OptionComponent.Expect<T>(self : OptionComponent<T>,msg : string) : T
233
+ assert(self:IsSome(),msg)
234
+ return self.Some :: T
235
+ end
236
+
237
+ --[[
238
+ Asserts that the Option is None, throwing error if Some
239
+ @param msg Error message to display if Option contains a value
240
+ @error Throws if Option is Some
241
+ ]]
242
+ function OptionComponent.ExpectNone<T>(self : OptionComponent<T>,msg : string)
243
+ assert(self:IsNone(),msg)
244
+ end
245
+
246
+ --[[
247
+ Unwraps the contained value, panicking with default message if None
248
+ @return The contained value
249
+ @error Throws "Called UnWrap() on None" if Option is None
250
+ ]]
251
+ function OptionComponent.UnWrap<T>(self : OptionComponent<T>)
252
+ return self:Expect("Called UnWrap() on None")
253
+ end
254
+
255
+ --[[
256
+ Unwraps the value or returns a default if None
257
+ Alias for GetOr
258
+ @param value Default value to return if None
259
+ @return The contained value or default
260
+ ]]
261
+ function OptionComponent.UnWrapOr<T, K>(self : OptionComponent<T>,value : K) : T | K
262
+ return self:GetOr(value)
263
+ end
264
+
265
+ --[[
266
+ Unwraps the value or computes a default if None
267
+ Alias for GetOrElse
268
+ @param callback Function to compute default if None
269
+ @return The contained value or computed default
270
+ ]]
271
+ function OptionComponent.UnWrapOrElse<T, K>(self : OptionComponent<T>,callback : Callback<K>) : T | K
272
+ return self:GetOrElse(callback)
273
+ end
274
+
275
+ --[[
276
+ Checks if the Option contains a specific value
277
+ @param value The value to check for
278
+ @return true if Option contains the exact value, false otherwise
279
+ ]]
280
+ function OptionComponent.Contains<T, K>(self : OptionComponent<T>,value : K)
281
+ return self:IsSome() and self.Some == value
282
+ end
283
+
284
+ --[[
285
+ String representation of the Option
286
+ @return "Option(value)" for Some, "Option(None)" for None
287
+ ]]
288
+ function OptionComponent.__tostring<T>(self : OptionComponent<T>)
289
+ if(self:IsSome()) then
290
+ return "Option("..`{self.Some}`..")"
291
+ else
292
+ return "Option(None)"
293
+ end
294
+ end
295
+
296
+ --[[
297
+ Serializes the Option for storage or transmission
298
+ @return Table with Tag and optional Value fields
299
+ ]]
300
+ function OptionComponent.Serialize<T>(self : OptionComponent<T>)
301
+ if(self:IsSome()) then
302
+ return {
303
+ Tag = self.Tag,
304
+ Value = self.Some :: T,
305
+ }
306
+ end
307
+ return {Tag = self.Tag}
308
+ end
309
+
310
+ --[[
311
+ Equality comparison between two Options
312
+ Two Options are equal if:
313
+ - Both are None, or
314
+ - Both are Some and contain equal values
315
+ @param b The other Option to compare with
316
+ @return true if Options are equal, false otherwise
317
+ ]]
318
+ function OptionComponent.__eq<T>(self : OptionComponent<T>,b : OptionComponent<T>)
319
+ local aIsOption = OptionConstructor.IsOption(self)
320
+ local bIsOption = OptionConstructor.IsOption(b)
321
+ if(not aIsOption or not bIsOption) then return false end
322
+ if(self:IsSome() and b:IsSome()) then
323
+ return self.Some == b.Some
324
+ elseif(self:IsSome() and b:IsNone()) then
325
+ return false
326
+ elseif(self:IsNone() and b:IsNone()) then
327
+ return true
328
+ else
329
+ return false
330
+ end
331
+ end
332
+
333
+ -- Lowercase aliases for methods (alternative naming convention)
334
+ -- These provide the same functionality with camelCase naming
335
+ OptionComponent.Unwrap = OptionComponent.UnWrap
336
+ OptionComponent.UnwrapOr = OptionComponent.UnWrapOr
337
+ OptionComponent.getOr = OptionComponent.GetOr
338
+ OptionComponent.getOrElse = OptionComponent.GetOrElse
339
+ OptionComponent.expectNone = OptionComponent.ExpectNone
340
+ OptionComponent.andThen = OptionComponent.AndThen
341
+ OptionComponent.map = OptionComponent.Map
342
+ OptionComponent.filter = OptionComponent.Filter
343
+ OptionComponent.assert = OptionComponent.Assert
344
+ OptionComponent.match = OptionComponent.Match
345
+ OptionComponent.contains = OptionComponent.Contains
346
+ OptionComponent.isNone = OptionComponent.IsNone
347
+ OptionComponent.isSome = OptionComponent.IsSome
348
+ OptionComponent.serialize = OptionComponent.Serialize
349
+
350
+ -- OptionConstructor lowercase aliases
351
+ OptionConstructor.isOption = OptionConstructor.IsOption
352
+ OptionConstructor.deserialize = OptionConstructor.Deserialize
353
+
354
+ -- Export the constructor table to create Options
355
+ return OptionConstructor
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/evxryy-option",
3
- "version": "1.2.03",
3
+ "version": "1.2.04",
4
4
  "description": "",
5
5
  "main": "out/init.lua",
6
6
  "scripts": {
@@ -36,5 +36,8 @@
36
36
  "prettier": "^3.8.1",
37
37
  "roblox-ts": "^3.0.0",
38
38
  "typescript": "^5.9.3"
39
+ },
40
+ "dependencies": {
41
+ "@rbxts/evxryy-option": "^1.2.3"
39
42
  }
40
43
  }