literal 1.5.0 → 1.7.0
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.
- checksums.yaml +4 -4
- data/lib/literal/array.rb +15 -15
- data/lib/literal/data_structure.rb +4 -3
- data/lib/literal/delegator.rb +25 -0
- data/lib/literal/enum.rb +4 -5
- data/lib/literal/flags/flags_16.rb +7 -0
- data/lib/literal/flags/flags_32.rb +7 -0
- data/lib/literal/flags/flags_64.rb +7 -0
- data/lib/literal/flags/flags_8.rb +7 -0
- data/lib/literal/flags.rb +0 -24
- data/lib/literal/hash.rb +1 -1
- data/lib/literal/properties/schema.rb +3 -3
- data/lib/literal/properties.rb +5 -6
- data/lib/literal/property.rb +3 -3
- data/lib/literal/rails/enum_type.rb +4 -0
- data/lib/literal/rails.rb +0 -3
- data/lib/literal/set.rb +1 -1
- data/lib/literal/transforms.rb +2 -2
- data/lib/literal/tuple.rb +2 -2
- data/lib/literal/types/array_type.rb +1 -0
- data/lib/literal/types/class_type.rb +3 -2
- data/lib/literal/types/constraint_type.rb +5 -4
- data/lib/literal/{deferred_type.rb → types/deferred_type.rb} +1 -1
- data/lib/literal/types/descendant_type.rb +2 -1
- data/lib/literal/types/enumerable_type.rb +2 -1
- data/lib/literal/types/frozen_type.rb +3 -2
- data/lib/literal/types/hash_type.rb +3 -2
- data/lib/literal/types/interface_type.rb +20 -14
- data/lib/literal/types/intersection_type.rb +4 -3
- data/lib/literal/types/map_type.rb +2 -1
- data/lib/literal/types/nilable_type.rb +3 -2
- data/lib/literal/types/not_type.rb +4 -3
- data/lib/literal/types/predicate_type.rb +22 -0
- data/lib/literal/types/range_type.rb +2 -1
- data/lib/literal/types/set_type.rb +2 -1
- data/lib/literal/types/tuple_type.rb +1 -0
- data/lib/literal/types/union_type.rb +46 -30
- data/lib/literal/types.rb +143 -87
- data/lib/literal/value.rb +65 -0
- data/lib/literal/version.rb +1 -1
- data/lib/literal.rb +82 -37
- metadata +26 -5
@@ -8,6 +8,7 @@ class Literal::Types::IntersectionType
|
|
8
8
|
raise Literal::ArgumentError.new("_Intersection type must have at least one type.") if types.size < 1
|
9
9
|
|
10
10
|
@types = types
|
11
|
+
freeze
|
11
12
|
end
|
12
13
|
|
13
14
|
attr_reader :types
|
@@ -35,17 +36,17 @@ class Literal::Types::IntersectionType
|
|
35
36
|
when Literal::Types::IntersectionType
|
36
37
|
@types.all? do |type|
|
37
38
|
other.types.any? do |other_type|
|
38
|
-
Literal.subtype?(other_type,
|
39
|
+
Literal.subtype?(other_type, type)
|
39
40
|
end
|
40
41
|
end
|
41
42
|
when Literal::Types::ConstraintType
|
42
43
|
@types.all? do |type|
|
43
44
|
other.object_constraints.any? do |object_constraint|
|
44
|
-
Literal.subtype?(object_constraint,
|
45
|
+
Literal.subtype?(object_constraint, type)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
when Literal::Types::FrozenType
|
48
|
-
@types.all? { |type| Literal.subtype?(other.type,
|
49
|
+
@types.all? { |type| Literal.subtype?(other.type, type) }
|
49
50
|
else
|
50
51
|
false
|
51
52
|
end
|
@@ -6,6 +6,7 @@ class Literal::Types::MapType
|
|
6
6
|
|
7
7
|
def initialize(**shape)
|
8
8
|
@shape = shape
|
9
|
+
freeze
|
9
10
|
end
|
10
11
|
|
11
12
|
attr_reader :shape
|
@@ -44,7 +45,7 @@ class Literal::Types::MapType
|
|
44
45
|
other_shape = other.shape
|
45
46
|
|
46
47
|
@shape.all? do |k, v|
|
47
|
-
Literal.subtype?(other_shape[k],
|
48
|
+
Literal.subtype?(other_shape[k], v)
|
48
49
|
end
|
49
50
|
else
|
50
51
|
false
|
@@ -6,6 +6,7 @@ class Literal::Types::NilableType
|
|
6
6
|
|
7
7
|
def initialize(type)
|
8
8
|
@type = type
|
9
|
+
freeze
|
9
10
|
end
|
10
11
|
|
11
12
|
attr_reader :type
|
@@ -25,11 +26,11 @@ class Literal::Types::NilableType
|
|
25
26
|
def >=(other)
|
26
27
|
case other
|
27
28
|
when Literal::Types::NilableType
|
28
|
-
Literal.subtype?(other.type,
|
29
|
+
Literal.subtype?(other.type, @type)
|
29
30
|
when nil
|
30
31
|
true
|
31
32
|
else
|
32
|
-
Literal.subtype?(other,
|
33
|
+
Literal.subtype?(other, @type)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
@@ -6,6 +6,7 @@ class Literal::Types::NotType
|
|
6
6
|
|
7
7
|
def initialize(type)
|
8
8
|
@type = type
|
9
|
+
freeze
|
9
10
|
end
|
10
11
|
|
11
12
|
attr_reader :type
|
@@ -21,11 +22,11 @@ class Literal::Types::NotType
|
|
21
22
|
def >=(other)
|
22
23
|
case other
|
23
24
|
when Literal::Types::NotType
|
24
|
-
Literal.subtype?(other.type,
|
25
|
+
Literal.subtype?(other.type, @type)
|
25
26
|
when Literal::Types::ConstraintType
|
26
|
-
other.object_constraints.any? { |constraint| Literal.subtype?(constraint,
|
27
|
+
other.object_constraints.any? { |constraint| Literal.subtype?(constraint, self) }
|
27
28
|
when Literal::Types::IntersectionType
|
28
|
-
other.types.any? { |type| Literal.subtype?(type,
|
29
|
+
other.types.any? { |type| Literal.subtype?(type, self) }
|
29
30
|
else
|
30
31
|
false
|
31
32
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Literal::Types::PredicateType
|
4
|
+
include Literal::Type
|
5
|
+
|
6
|
+
def initialize(message:, block:)
|
7
|
+
@message = message
|
8
|
+
@block = block
|
9
|
+
|
10
|
+
freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
%(_Predicate("#{@message}"))
|
15
|
+
end
|
16
|
+
|
17
|
+
def ===(other)
|
18
|
+
@block === other
|
19
|
+
end
|
20
|
+
|
21
|
+
freeze
|
22
|
+
end
|
@@ -6,6 +6,7 @@ class Literal::Types::RangeType
|
|
6
6
|
|
7
7
|
def initialize(type)
|
8
8
|
@type = type
|
9
|
+
freeze
|
9
10
|
end
|
10
11
|
|
11
12
|
attr_reader :type
|
@@ -27,7 +28,7 @@ class Literal::Types::RangeType
|
|
27
28
|
def >=(other)
|
28
29
|
case other
|
29
30
|
when Literal::Types::RangeType
|
30
|
-
Literal.subtype?(other.type,
|
31
|
+
Literal.subtype?(other.type, @type)
|
31
32
|
else
|
32
33
|
false
|
33
34
|
end
|
@@ -6,6 +6,7 @@ class Literal::Types::SetType
|
|
6
6
|
|
7
7
|
def initialize(type)
|
8
8
|
@type = type
|
9
|
+
freeze
|
9
10
|
end
|
10
11
|
|
11
12
|
attr_reader :type
|
@@ -37,7 +38,7 @@ class Literal::Types::SetType
|
|
37
38
|
def >=(other)
|
38
39
|
case other
|
39
40
|
when Literal::Types::SetType
|
40
|
-
Literal.subtype?(other.type,
|
41
|
+
Literal.subtype?(other.type, @type)
|
41
42
|
else
|
42
43
|
false
|
43
44
|
end
|
@@ -2,74 +2,90 @@
|
|
2
2
|
|
3
3
|
class Literal::Types::UnionType
|
4
4
|
include Enumerable
|
5
|
+
include Literal::Type
|
5
6
|
|
6
|
-
def initialize(*
|
7
|
-
raise Literal::ArgumentError.new("_Union type must have at least one type.") if
|
7
|
+
def initialize(*queue)
|
8
|
+
raise Literal::ArgumentError.new("_Union type must have at least one type.") if queue.size < 1
|
9
|
+
types = []
|
10
|
+
primitives = Set[]
|
11
|
+
|
12
|
+
while queue.length > 0
|
13
|
+
type = queue.shift
|
14
|
+
case type
|
15
|
+
when Literal::Types::UnionType
|
16
|
+
queue.concat(type.types, type.primitives.to_a)
|
17
|
+
when Array, Hash, String, Symbol, Integer, Float, Complex, Rational, true, false, nil
|
18
|
+
primitives << type
|
19
|
+
else
|
20
|
+
types << type
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
types.uniq!
|
25
|
+
@types = types
|
26
|
+
@primitives = primitives
|
8
27
|
|
9
|
-
@types = []
|
10
|
-
load_types(types)
|
11
|
-
@types.uniq!
|
12
28
|
@types.freeze
|
29
|
+
@primitives.freeze
|
30
|
+
freeze
|
13
31
|
end
|
14
32
|
|
15
|
-
attr_reader :types
|
33
|
+
attr_reader :types, :primitives
|
16
34
|
|
17
35
|
def inspect
|
18
|
-
"_Union(#{
|
36
|
+
"_Union(#{to_a.map(&:inspect).join(', ')})"
|
19
37
|
end
|
20
38
|
|
21
39
|
def ===(value)
|
40
|
+
return true if @primitives.include?(value)
|
41
|
+
|
22
42
|
types = @types
|
43
|
+
|
23
44
|
i, len = 0, types.size
|
24
45
|
while i < len
|
25
46
|
return true if types[i] === value
|
26
47
|
i += 1
|
27
48
|
end
|
49
|
+
|
50
|
+
false
|
28
51
|
end
|
29
52
|
|
30
53
|
def each(&)
|
54
|
+
@primitives.each(&)
|
31
55
|
@types.each(&)
|
32
56
|
end
|
33
57
|
|
34
58
|
def deconstruct
|
35
|
-
|
59
|
+
to_a
|
36
60
|
end
|
37
61
|
|
38
62
|
def [](key)
|
39
|
-
if @types.include?(key)
|
63
|
+
if @primitives.include?(key) || @types.include?(key)
|
40
64
|
key
|
41
|
-
else
|
42
|
-
raise ArgumentError.new("#{key} not in #{inspect}")
|
43
65
|
end
|
44
66
|
end
|
45
67
|
|
46
|
-
def
|
47
|
-
|
48
|
-
ctx.add_child(label: type.inspect, expected: type, actual: ctx.actual)
|
49
|
-
end
|
50
|
-
ctx.children.clear if ctx.children.none? { |c| c.children.any? }
|
68
|
+
def fetch(key)
|
69
|
+
self[key] or raise KeyError.new("Key not found: #{key.inspect}")
|
51
70
|
end
|
52
71
|
|
53
72
|
def >=(other)
|
73
|
+
types = @types
|
74
|
+
primitives = @primitives
|
75
|
+
|
54
76
|
case other
|
55
77
|
when Literal::Types::UnionType
|
56
|
-
other.types.all? do |other_type|
|
57
|
-
|
58
|
-
Literal.subtype?(type, of: other_type)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
else
|
62
|
-
@types.any? do |type|
|
63
|
-
Literal.subtype?(other, of: type)
|
78
|
+
types_have_at_least_one_subtype = other.types.all? do |other_type|
|
79
|
+
primitives.any? { |p| Literal.subtype?(other_type, p) } || types.any? { |t| Literal.subtype?(other_type, t) }
|
64
80
|
end
|
65
|
-
end
|
66
|
-
end
|
67
81
|
|
68
|
-
|
82
|
+
primitives_have_at_least_one_subtype = other.primitives.all? do |other_primitive|
|
83
|
+
primitives.any? { |p| Literal.subtype?(other_primitive, p) } || types.any? { |t| Literal.subtype?(other_primitive, t) }
|
84
|
+
end
|
69
85
|
|
70
|
-
|
71
|
-
|
72
|
-
|
86
|
+
types_have_at_least_one_subtype && primitives_have_at_least_one_subtype
|
87
|
+
else
|
88
|
+
types.any? { |t| Literal.subtype?(other, t) } || primitives.any? { |p| Literal.subtype?(other, p) }
|
73
89
|
end
|
74
90
|
end
|
75
91
|
|
data/lib/literal/types.rb
CHANGED
@@ -1,150 +1,177 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Literal::Types
|
4
|
-
|
5
|
-
autoload :ArrayType, "literal/types/array_type"
|
6
|
-
autoload :BooleanType, "literal/types/boolean_type"
|
7
|
-
autoload :ClassType, "literal/types/class_type"
|
8
|
-
autoload :ConstraintType, "literal/types/constraint_type"
|
9
|
-
autoload :DeferredType, "literal/deferred_type"
|
10
|
-
autoload :DescendantType, "literal/types/descendant_type"
|
11
|
-
autoload :EnumerableType, "literal/types/enumerable_type"
|
12
|
-
autoload :FalsyType, "literal/types/falsy_type"
|
13
|
-
autoload :FrozenType, "literal/types/frozen_type"
|
14
|
-
autoload :HashType, "literal/types/hash_type"
|
15
|
-
autoload :InterfaceType, "literal/types/interface_type"
|
16
|
-
autoload :IntersectionType, "literal/types/intersection_type"
|
17
|
-
autoload :JSONDataType, "literal/types/json_data_type"
|
18
|
-
autoload :MapType, "literal/types/map_type"
|
19
|
-
autoload :NeverType, "literal/types/never_type"
|
20
|
-
autoload :NilableType, "literal/types/nilable_type"
|
21
|
-
autoload :NotType, "literal/types/not_type"
|
22
|
-
autoload :RangeType, "literal/types/range_type"
|
23
|
-
autoload :SetType, "literal/types/set_type"
|
24
|
-
autoload :TruthyType, "literal/types/truthy_type"
|
25
|
-
autoload :TupleType, "literal/types/tuple_type"
|
26
|
-
autoload :UnionType, "literal/types/union_type"
|
27
|
-
autoload :VoidType, "literal/types/void_type"
|
28
|
-
|
29
|
-
ProcableType = InterfaceType.new(:to_proc).freeze
|
30
|
-
CallableType = InterfaceType.new(:call).freeze
|
31
|
-
LambdaType = ConstraintType.new(Proc, lambda?: true).freeze
|
32
|
-
|
33
|
-
NilableBooleanType = NilableType.new(BooleanType::Instance).freeze
|
34
|
-
NilableCallableType = NilableType.new(CallableType).freeze
|
35
|
-
NilableJSONDataType = NilableType.new(JSONDataType).freeze
|
36
|
-
NilableLambdaType = NilableType.new(LambdaType).freeze
|
37
|
-
NilableProcableType = NilableType.new(ProcableType).freeze
|
4
|
+
extend self
|
38
5
|
|
39
6
|
# Matches any value except `nil`. Use `_Any?` or `_Void` to match any value including `nil`.
|
7
|
+
# ```ruby
|
8
|
+
# _Any
|
9
|
+
# ```
|
40
10
|
def _Any
|
41
11
|
AnyType::Instance
|
42
12
|
end
|
43
13
|
|
14
|
+
# Matches any value including `nil`. This is the same as `_Void` and the opposite of `_Never`.
|
15
|
+
# ```ruby
|
16
|
+
# _Any?
|
17
|
+
# ```
|
44
18
|
def _Any?
|
45
19
|
VoidType::Instance
|
46
20
|
end
|
47
21
|
|
48
|
-
# Matches if the value is an `Array` and all the elements match the given type.
|
49
|
-
|
50
|
-
|
22
|
+
# Matches if the value is an `Array` and all the elements of the array match the given type.
|
23
|
+
# ```ruby
|
24
|
+
# _Array(String)
|
25
|
+
# ```
|
26
|
+
def _Array(type)
|
27
|
+
ArrayType.new(type)
|
51
28
|
end
|
52
29
|
|
53
|
-
# Nilable version of `_Array
|
54
|
-
|
55
|
-
|
56
|
-
|
30
|
+
# Nilable version of `_Array`.
|
31
|
+
# ```ruby
|
32
|
+
# _Array?(String)
|
33
|
+
# ```
|
34
|
+
def _Array?(type)
|
35
|
+
_Nilable(
|
36
|
+
_Array(type)
|
57
37
|
)
|
58
38
|
end
|
59
39
|
|
60
|
-
# Matches if the value is `true` or `false`.
|
40
|
+
# Matches if the value is either `true` or `false`. This is equivalent to `_Union(true, false)`.
|
41
|
+
# ```ruby
|
42
|
+
# _Boolean
|
43
|
+
# ```
|
61
44
|
def _Boolean
|
62
45
|
BooleanType::Instance
|
63
46
|
end
|
64
47
|
|
65
|
-
# Nilable version of `_Boolean
|
48
|
+
# Nilable version of `_Boolean`.
|
49
|
+
# ```ruby
|
50
|
+
# _Boolean?
|
51
|
+
# ```
|
66
52
|
def _Boolean?
|
67
53
|
NilableBooleanType
|
68
54
|
end
|
69
55
|
|
70
56
|
# Matches if the value responds to `#call`.
|
57
|
+
# ```ruby
|
58
|
+
# _Callable
|
59
|
+
# ```
|
71
60
|
def _Callable
|
72
61
|
CallableType
|
73
62
|
end
|
74
63
|
|
75
|
-
#
|
64
|
+
# Nilable version of `_Callable`.
|
65
|
+
# ```ruby
|
66
|
+
# _Callable?
|
67
|
+
# ```
|
76
68
|
def _Callable?
|
77
69
|
NilableCallableType
|
78
70
|
end
|
79
71
|
|
80
72
|
# Matches if the value either the given class or a subclass of it.
|
81
|
-
|
82
|
-
|
73
|
+
# ```ruby
|
74
|
+
# _Class(ActiveRecord::Base)
|
75
|
+
# ```
|
76
|
+
def _Class(expected_class)
|
77
|
+
ClassType.new(expected_class)
|
83
78
|
end
|
84
79
|
|
85
|
-
# Nilable version of `_Class
|
80
|
+
# Nilable version of `_Class`.
|
81
|
+
# ```ruby
|
82
|
+
# _Class?(ActiveRecord::Base)
|
83
|
+
# ```
|
86
84
|
def _Class?(...)
|
87
|
-
|
88
|
-
|
85
|
+
_Nilable(
|
86
|
+
_Class(...)
|
89
87
|
)
|
90
88
|
end
|
91
89
|
|
92
90
|
# Similar to `_Intersection`, but allows you to specify attribute constraints as keyword arguments.
|
93
|
-
#
|
94
|
-
#
|
95
|
-
|
96
|
-
|
91
|
+
# ```ruby
|
92
|
+
# _Constraint(Array, size: 1..3)
|
93
|
+
# ```
|
94
|
+
def _Constraint(*a, **k)
|
95
|
+
if a.length == 1 && k.length == 0
|
96
|
+
a[0]
|
97
|
+
else
|
98
|
+
ConstraintType.new(*a, **k)
|
99
|
+
end
|
97
100
|
end
|
98
101
|
|
99
102
|
# Nilable version of `_Constraint`
|
103
|
+
# ```ruby
|
104
|
+
# _Constraint?(Array, size: 1..3)
|
105
|
+
# ```
|
100
106
|
def _Constraint?(...)
|
101
|
-
|
102
|
-
|
107
|
+
_Nilable(
|
108
|
+
_Constraint(...)
|
103
109
|
)
|
104
110
|
end
|
105
111
|
|
106
112
|
# Matches if the value is a `Date` and matches the given constraints.
|
107
|
-
# If you don't need any constraints, use `Date` instead of `_Date`.
|
113
|
+
# If you don't need any constraints, use `Date` instead of `_Date`. See also `_Constraint`.
|
114
|
+
# ```ruby
|
115
|
+
# _Date((Date.today)..)
|
116
|
+
# _Date(year: 2025)
|
117
|
+
# ```
|
108
118
|
def _Date(...)
|
109
119
|
_Constraint(Date, ...)
|
110
120
|
end
|
111
121
|
|
112
|
-
# Nilable version of `_Date
|
122
|
+
# Nilable version of `_Date`.
|
113
123
|
def _Date?(...)
|
114
124
|
_Nilable(
|
115
125
|
_Date(...)
|
116
126
|
)
|
117
127
|
end
|
118
128
|
|
119
|
-
|
120
|
-
|
129
|
+
# Takes a type as a block so it can be resolved when needed. This is useful if declaring your type now would cause an error because constants haven’t been defined yet.
|
130
|
+
# ```ruby
|
131
|
+
# _Deferred { _Class(SomeFutureConstant) }
|
132
|
+
# ```
|
133
|
+
def _Deferred(&type)
|
134
|
+
DeferredType.new(&type)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Nilable version of `_Deferred`.
|
138
|
+
def _Deferred?(&type)
|
139
|
+
_Nilable(
|
140
|
+
_Deferred(&type)
|
141
|
+
)
|
121
142
|
end
|
122
143
|
|
123
144
|
# Matches if the value is a descendant of the given class.
|
145
|
+
# ```ruby
|
146
|
+
# _Descendant(ActiveRecord::Base)
|
147
|
+
# ```
|
124
148
|
def _Descendant(...)
|
125
149
|
DescendantType.new(...)
|
126
150
|
end
|
127
151
|
|
128
|
-
# Nilable version of `_Descendant
|
152
|
+
# Nilable version of `_Descendant`.
|
129
153
|
def _Descendant?(...)
|
130
|
-
|
131
|
-
|
154
|
+
_Nilable(
|
155
|
+
_Descendant(...)
|
132
156
|
)
|
133
157
|
end
|
134
158
|
|
135
159
|
# Matches if the value is an `Enumerable` and all its elements match the given type.
|
136
|
-
|
137
|
-
|
160
|
+
# ```ruby
|
161
|
+
# _Enumerable(String)
|
162
|
+
# ```
|
163
|
+
def _Enumerable(type)
|
164
|
+
EnumerableType.new(type)
|
138
165
|
end
|
139
166
|
|
140
|
-
# Nilable version of `_Enumerable
|
167
|
+
# Nilable version of `_Enumerable`.
|
141
168
|
def _Enumerable?(...)
|
142
|
-
|
143
|
-
|
169
|
+
_Nilable(
|
170
|
+
_Enumerable(...)
|
144
171
|
)
|
145
172
|
end
|
146
173
|
|
147
|
-
# Matches *"falsy"* values (`nil` and `false`).
|
174
|
+
# Matches *"falsy"* values (`nil` and `false`). This is equivalent to `_Nilable(false)` or `_Union(nil, false)`.
|
148
175
|
def _Falsy
|
149
176
|
FalsyType::Instance
|
150
177
|
end
|
@@ -152,11 +179,14 @@ module Literal::Types
|
|
152
179
|
# Matches if the value is a `Float` and matches the given constraints.
|
153
180
|
# You could use a `Range`, for example, as a constraint.
|
154
181
|
# If you don't need a constraint, use `Float` instead of `_Float`.
|
182
|
+
# ```ruby
|
183
|
+
# _Float(5..10)
|
184
|
+
# ```
|
155
185
|
def _Float(...)
|
156
186
|
_Constraint(Float, ...)
|
157
187
|
end
|
158
188
|
|
159
|
-
# Nilable version of `_Float
|
189
|
+
# Nilable version of `_Float`.
|
160
190
|
def _Float?(...)
|
161
191
|
_Nilable(
|
162
192
|
_Float(...)
|
@@ -170,8 +200,8 @@ module Literal::Types
|
|
170
200
|
|
171
201
|
# Nilable version of `_Frozen`
|
172
202
|
def _Frozen?(...)
|
173
|
-
|
174
|
-
|
203
|
+
_Nilable(
|
204
|
+
_Frozen(...)
|
175
205
|
)
|
176
206
|
end
|
177
207
|
|
@@ -182,8 +212,8 @@ module Literal::Types
|
|
182
212
|
|
183
213
|
# Nilable version of `_Hash`
|
184
214
|
def _Hash?(...)
|
185
|
-
|
186
|
-
|
215
|
+
_Nilable(
|
216
|
+
_Hash(...)
|
187
217
|
)
|
188
218
|
end
|
189
219
|
|
@@ -210,8 +240,8 @@ module Literal::Types
|
|
210
240
|
|
211
241
|
# Nilable version of `_Interface`
|
212
242
|
def _Interface?(...)
|
213
|
-
|
214
|
-
|
243
|
+
_Nilable(
|
244
|
+
_Interface(...)
|
215
245
|
)
|
216
246
|
end
|
217
247
|
|
@@ -222,8 +252,8 @@ module Literal::Types
|
|
222
252
|
|
223
253
|
# Nilable version of `_Intersection`
|
224
254
|
def _Intersection?(...)
|
225
|
-
|
226
|
-
|
255
|
+
_Nilable(
|
256
|
+
_Intersection(...)
|
227
257
|
)
|
228
258
|
end
|
229
259
|
|
@@ -247,14 +277,20 @@ module Literal::Types
|
|
247
277
|
NilableLambdaType
|
248
278
|
end
|
249
279
|
|
280
|
+
# ```ruby
|
281
|
+
# _Map(name: String, age: Integer)
|
282
|
+
# ```
|
250
283
|
def _Map(...)
|
251
284
|
MapType.new(...)
|
252
285
|
end
|
253
286
|
|
254
287
|
# Nilable version of `_Map`
|
288
|
+
# ```ruby
|
289
|
+
# _Map?(name: String, age: Integer)
|
290
|
+
# ```
|
255
291
|
def _Map?(...)
|
256
|
-
|
257
|
-
|
292
|
+
_Nilable(
|
293
|
+
_Map(...)
|
258
294
|
)
|
259
295
|
end
|
260
296
|
|
@@ -278,6 +314,10 @@ module Literal::Types
|
|
278
314
|
end
|
279
315
|
end
|
280
316
|
|
317
|
+
def _Predicate(message, &block)
|
318
|
+
PredicateType.new(message:, block:)
|
319
|
+
end
|
320
|
+
|
281
321
|
# Matches if the value is a `Proc` or responds to `#to_proc`.
|
282
322
|
def _Procable
|
283
323
|
ProcableType
|
@@ -295,8 +335,8 @@ module Literal::Types
|
|
295
335
|
|
296
336
|
# Nilable version of `_Range`
|
297
337
|
def _Range?(...)
|
298
|
-
|
299
|
-
|
338
|
+
_Nilable(
|
339
|
+
_Range(...)
|
300
340
|
)
|
301
341
|
end
|
302
342
|
|
@@ -307,8 +347,8 @@ module Literal::Types
|
|
307
347
|
|
308
348
|
# Nilable version of `_Set`
|
309
349
|
def _Set?(...)
|
310
|
-
|
311
|
-
|
350
|
+
_Nilable(
|
351
|
+
_Set(...)
|
312
352
|
)
|
313
353
|
end
|
314
354
|
|
@@ -356,14 +396,20 @@ module Literal::Types
|
|
356
396
|
end
|
357
397
|
|
358
398
|
# Matches if the value is an `Array` and each element matches the given types in order.
|
399
|
+
# ```ruby
|
400
|
+
# _Tuple(String, Integer, Integer)
|
401
|
+
# ```
|
359
402
|
def _Tuple(...)
|
360
403
|
TupleType.new(...)
|
361
404
|
end
|
362
405
|
|
363
406
|
# Nilable version of `_Typle`
|
407
|
+
# ```ruby
|
408
|
+
# _Tuple?(String, Integer, Integer)
|
409
|
+
# ```
|
364
410
|
def _Tuple?(...)
|
365
|
-
|
366
|
-
|
411
|
+
_Nilable(
|
412
|
+
_Tuple(...)
|
367
413
|
)
|
368
414
|
end
|
369
415
|
|
@@ -374,12 +420,22 @@ module Literal::Types
|
|
374
420
|
|
375
421
|
# Nilable version of `_Union`
|
376
422
|
def _Union?(...)
|
377
|
-
|
378
|
-
|
423
|
+
_Nilable(
|
424
|
+
_Union(...)
|
379
425
|
)
|
380
426
|
end
|
381
427
|
|
382
428
|
def _Void
|
383
429
|
VoidType::Instance
|
384
430
|
end
|
431
|
+
|
432
|
+
ProcableType = _Interface(:to_proc)
|
433
|
+
CallableType = _Interface(:call)
|
434
|
+
LambdaType = _Constraint(Proc, lambda?: true)
|
435
|
+
|
436
|
+
NilableBooleanType = _Nilable(BooleanType::Instance)
|
437
|
+
NilableCallableType = _Nilable(CallableType)
|
438
|
+
NilableJSONDataType = _Nilable(JSONDataType)
|
439
|
+
NilableLambdaType = _Nilable(LambdaType)
|
440
|
+
NilableProcableType = _Nilable(ProcableType)
|
385
441
|
end
|