dry-types 1.0.1 → 1.2.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/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +10 -0
- data/.github/ISSUE_TEMPLATE/---bug-report.md +34 -0
- data/.github/ISSUE_TEMPLATE/---feature-request.md +18 -0
- data/.travis.yml +10 -4
- data/CHANGELOG.md +101 -3
- data/Gemfile +9 -6
- data/README.md +2 -2
- data/Rakefile +2 -2
- data/benchmarks/hash_schemas.rb +8 -6
- data/benchmarks/lax_schema.rb +0 -1
- data/benchmarks/profile_invalid_input.rb +1 -1
- data/benchmarks/profile_lax_schema_valid.rb +1 -1
- data/benchmarks/profile_valid_input.rb +1 -1
- data/docsite/source/array-with-member.html.md +13 -0
- data/docsite/source/built-in-types.html.md +116 -0
- data/docsite/source/constraints.html.md +31 -0
- data/docsite/source/custom-types.html.md +93 -0
- data/docsite/source/default-values.html.md +91 -0
- data/docsite/source/enum.html.md +69 -0
- data/docsite/source/getting-started.html.md +57 -0
- data/docsite/source/hash-schemas.html.md +169 -0
- data/docsite/source/index.html.md +155 -0
- data/docsite/source/map.html.md +17 -0
- data/docsite/source/optional-values.html.md +96 -0
- data/docsite/source/sum.html.md +21 -0
- data/dry-types.gemspec +19 -19
- data/lib/dry/types.rb +9 -4
- data/lib/dry/types/array.rb +6 -0
- data/lib/dry/types/array/constructor.rb +32 -0
- data/lib/dry/types/array/member.rb +8 -1
- data/lib/dry/types/builder.rb +1 -1
- data/lib/dry/types/builder_methods.rb +33 -23
- data/lib/dry/types/coercions.rb +19 -6
- data/lib/dry/types/coercions/params.rb +4 -4
- data/lib/dry/types/constrained.rb +5 -0
- data/lib/dry/types/constructor.rb +5 -37
- data/lib/dry/types/constructor/function.rb +4 -5
- data/lib/dry/types/core.rb +27 -8
- data/lib/dry/types/decorator.rb +1 -1
- data/lib/dry/types/enum.rb +1 -0
- data/lib/dry/types/extensions.rb +4 -0
- data/lib/dry/types/extensions/maybe.rb +9 -1
- data/lib/dry/types/extensions/monads.rb +29 -0
- data/lib/dry/types/hash.rb +10 -11
- data/lib/dry/types/hash/constructor.rb +5 -5
- data/lib/dry/types/json.rb +4 -0
- data/lib/dry/types/lax.rb +4 -4
- data/lib/dry/types/map.rb +8 -4
- data/lib/dry/types/module.rb +3 -3
- data/lib/dry/types/nominal.rb +3 -4
- data/lib/dry/types/params.rb +9 -0
- data/lib/dry/types/predicate_inferrer.rb +197 -0
- data/lib/dry/types/predicate_registry.rb +34 -0
- data/lib/dry/types/primitive_inferrer.rb +97 -0
- data/lib/dry/types/printer.rb +17 -12
- data/lib/dry/types/schema.rb +14 -20
- data/lib/dry/types/schema/key.rb +19 -1
- data/lib/dry/types/spec/types.rb +3 -6
- data/lib/dry/types/version.rb +1 -1
- metadata +79 -52
@@ -0,0 +1,155 @@
|
|
1
|
+
---
|
2
|
+
title: Introduction
|
3
|
+
layout: gem-single
|
4
|
+
type: gem
|
5
|
+
name: dry-types
|
6
|
+
sections:
|
7
|
+
- getting-started
|
8
|
+
- built-in-types
|
9
|
+
- optional-values
|
10
|
+
- default-values
|
11
|
+
- sum
|
12
|
+
- constraints
|
13
|
+
- hash-schemas
|
14
|
+
- array-with-member
|
15
|
+
- enum
|
16
|
+
- map
|
17
|
+
- custom-types
|
18
|
+
---
|
19
|
+
|
20
|
+
`dry-types` is a simple and extendable type system for Ruby; useful for value coercions, applying constraints, defining complex structs or value objects and more. It was created as a successor to [Virtus](https://github.com/solnic/virtus).
|
21
|
+
|
22
|
+
### Example usage
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
require 'dry-types'
|
26
|
+
require 'dry-struct'
|
27
|
+
|
28
|
+
module Types
|
29
|
+
include Dry.Types()
|
30
|
+
end
|
31
|
+
|
32
|
+
User = Dry.Struct(name: Types::String, age: Types::Integer)
|
33
|
+
|
34
|
+
User.new(name: 'Bob', age: 35)
|
35
|
+
# => #<User name="Bob" age=35>
|
36
|
+
```
|
37
|
+
|
38
|
+
See [Built-in Types](/gems/dry-types/1.0/built-in-types/) for a full list of available types.
|
39
|
+
|
40
|
+
By themselves, the basic type definitions like `Types::String` and `Types::Integer` don't do anything except provide documentation about which type an attribute is expected to have. However, there are many more advanced possibilities:
|
41
|
+
|
42
|
+
- `Strict` types will raise an error if passed an attribute of the wrong type:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
class User < Dry::Struct
|
46
|
+
attribute :name, Types::Strict::String
|
47
|
+
attribute :age, Types::Strict::Integer
|
48
|
+
end
|
49
|
+
|
50
|
+
User.new(name: 'Bob', age: '18')
|
51
|
+
# => Dry::Struct::Error: [User.new] "18" (String) has invalid type for :age
|
52
|
+
```
|
53
|
+
|
54
|
+
- `Coercible` types will attempt to convert an attribute to the correct class
|
55
|
+
using Ruby's built-in coercion methods:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class User < Dry::Struct
|
59
|
+
attribute :name, Types::Coercible::String
|
60
|
+
attribute :age, Types::Coercible::Integer
|
61
|
+
end
|
62
|
+
|
63
|
+
User.new(name: 'Bob', age: '18')
|
64
|
+
# => #<User name="Bob" age=18>
|
65
|
+
User.new(name: 'Bob', age: 'not coercible')
|
66
|
+
# => ArgumentError: invalid value for Integer(): "not coercible"
|
67
|
+
```
|
68
|
+
|
69
|
+
- Use `.optional` to denote that an attribute can be `nil` (see [Optional Values](/gems/dry-types/1.0/optional-values)):
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
class User < Dry::Struct
|
73
|
+
attribute :name, Types::String
|
74
|
+
attribute :age, Types::Integer.optional
|
75
|
+
end
|
76
|
+
|
77
|
+
User.new(name: 'Bob', age: nil)
|
78
|
+
# => #<User name="Bob" age=nil>
|
79
|
+
# name is not optional:
|
80
|
+
User.new(name: nil, age: 18)
|
81
|
+
# => Dry::Struct::Error: [User.new] nil (NilClass) has invalid type for :name
|
82
|
+
# keys must still be present:
|
83
|
+
User.new(name: 'Bob')
|
84
|
+
# => Dry::Struct::Error: [User.new] :age is missing in Hash input
|
85
|
+
```
|
86
|
+
|
87
|
+
- Add custom constraints (see [Constraints](/gems/dry-types/1.0/constraints.html)):
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
class User < Dry::Struct
|
91
|
+
attribute :name, Types::Strict::String
|
92
|
+
attribute :age, Types::Strict::Integer.constrained(gteq: 18)
|
93
|
+
end
|
94
|
+
|
95
|
+
User.new(name: 'Bob', age: 17)
|
96
|
+
# => Dry::Struct::Error: [User.new] 17 (Fixnum) has invalid type for :age
|
97
|
+
```
|
98
|
+
|
99
|
+
- Add custom metadata to a type:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
class User < Dry::Struct
|
103
|
+
attribute :name, Types::String
|
104
|
+
attribute :age, Types::Integer.meta(info: 'extra info about age')
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
- Pass values directly to `Dry::Types` without creating an object using `[]`:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
Types::Strict::String["foo"]
|
112
|
+
# => "foo"
|
113
|
+
Types::Strict::String["10000"]
|
114
|
+
# => "10000"
|
115
|
+
Types::Coercible::String[10000]
|
116
|
+
# => "10000"
|
117
|
+
Types::Strict::String[10000]
|
118
|
+
# Dry::Types::ConstraintError: 1000 violates constraints
|
119
|
+
```
|
120
|
+
|
121
|
+
### Features
|
122
|
+
|
123
|
+
* Support for [constrained types](/gems/dry-types/1.0/constraints)
|
124
|
+
* Support for [optional values](/gems/dry-types/1.0/optional-values)
|
125
|
+
* Support for [default values](/gems/dry-types/1.0/default-values)
|
126
|
+
* Support for [sum types](/gems/dry-types/1.0/sum)
|
127
|
+
* Support for [enums](/gems/dry-types/1.0/enum)
|
128
|
+
* Support for [hash type with type schemas](/gems/dry-types/1.0/hash-schemas)
|
129
|
+
* Support for [array type with members](/gems/dry-types/1.0/array-with-member)
|
130
|
+
* Support for arbitrary meta information
|
131
|
+
* Support for typed struct objects via [dry-struct](/gems/dry-struct)
|
132
|
+
* Types are [categorized](/gems/dry-types/1.0/built-in-types), which is especially important for optimized and dedicated coercion logic
|
133
|
+
* Types are composable and reusable objects
|
134
|
+
* No const-missing magic and complicated const lookups
|
135
|
+
* Roughly 6-10 x faster than Virtus
|
136
|
+
|
137
|
+
### Use cases
|
138
|
+
|
139
|
+
`dry-types` is suitable for many use-cases, for example:
|
140
|
+
|
141
|
+
* Value coercions
|
142
|
+
* Processing arrays
|
143
|
+
* Processing hashes with explicit schemas
|
144
|
+
* Defining various domain-specific information shared between multiple parts of your application
|
145
|
+
* Annotating objects
|
146
|
+
|
147
|
+
### Other gems using dry-types
|
148
|
+
|
149
|
+
`dry-types` is often used as a low-level abstraction. The following gems use it already:
|
150
|
+
|
151
|
+
* [dry-struct](/gems/dry-struct)
|
152
|
+
* [dry-initializer](/gems/dry-initializer)
|
153
|
+
* [Hanami](http://hanamirb.org)
|
154
|
+
* [rom-rb](http://rom-rb.org)
|
155
|
+
* [Trailblazer](http://trailblazer.to)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
title: Map
|
3
|
+
layout: gem-single
|
4
|
+
name: dry-types
|
5
|
+
---
|
6
|
+
|
7
|
+
`Map` describes a homogeneous hashmap. This means only types of keys and values are known. You can simply imagine a map input as a list of key-value pairs.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
int_float_hash = Types::Hash.map(Types::Integer, Types::Float)
|
11
|
+
int_float_hash[100 => 300.0, 42 => 70.0]
|
12
|
+
# => {100=>300.0, 42=>70.0}
|
13
|
+
|
14
|
+
# Only accepts mappings of integers to floats
|
15
|
+
int_float_hash[name: 'Jane']
|
16
|
+
# => Dry::Types::MapError: input key :name is invalid: type?(Integer, :name)
|
17
|
+
```
|
@@ -0,0 +1,96 @@
|
|
1
|
+
---
|
2
|
+
title: Type Attributes
|
3
|
+
layout: gem-single
|
4
|
+
name: dry-types
|
5
|
+
---
|
6
|
+
|
7
|
+
Types themselves have optional attributes you can apply to get further functionality.
|
8
|
+
|
9
|
+
### Append `.optional` to a _Type_ to allow `nil`
|
10
|
+
|
11
|
+
By default, nil values raise an error:
|
12
|
+
|
13
|
+
``` ruby
|
14
|
+
Types::Strict::String[nil]
|
15
|
+
# => raises Dry::Types::ConstraintError
|
16
|
+
```
|
17
|
+
|
18
|
+
Add `.optional` and `nil` values become valid:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
optional_string = Types::Strict::String.optional
|
22
|
+
|
23
|
+
optional_string[nil]
|
24
|
+
# => nil
|
25
|
+
optional_string['something']
|
26
|
+
# => "something"
|
27
|
+
optional_string[123]
|
28
|
+
# raises Dry::Types::ConstraintError
|
29
|
+
```
|
30
|
+
|
31
|
+
`Types::String.optional` is just syntactic sugar for `Types::Strict::Nil | Types::Strict::String`.
|
32
|
+
|
33
|
+
### Handle optional values using Monads
|
34
|
+
|
35
|
+
The [dry-monads gem](/gems/dry-monads/) provides another approach to handling optional values by returning a [_Monad_](/gems/dry-monads/) object. This allows you to pass your type to a `Maybe(x)` block that only executes if `x` returns `Some` or `None`.
|
36
|
+
|
37
|
+
> NOTE: Requires the [dry-monads gem](/gems/dry-monads/) to be loaded.
|
38
|
+
|
39
|
+
1. Load the `:maybe` extension in your application.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
require 'dry-types'
|
43
|
+
|
44
|
+
Dry::Types.load_extensions(:maybe)
|
45
|
+
module Types
|
46
|
+
include Dry.Types()
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
2. Append `.maybe` to a _Type_ to return a _Monad_ object
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
x = Types::Maybe::Strict::Integer[nil]
|
54
|
+
Maybe(x) { puts(x) }
|
55
|
+
|
56
|
+
x = Types::Maybe::Coercible::String[nil]
|
57
|
+
Maybe(x) { puts(x) }
|
58
|
+
|
59
|
+
x = Types::Maybe::Strict::Integer[123]
|
60
|
+
Maybe(x) { puts(x) }
|
61
|
+
|
62
|
+
x = Types::Maybe::Strict::String[123]
|
63
|
+
Maybe(x) { puts(x) }
|
64
|
+
```
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
Types::Maybe::Strict::Integer[nil] # None
|
68
|
+
Types::Maybe::Strict::Integer[123] # Some(123)
|
69
|
+
|
70
|
+
Types::Maybe::Coercible::Float[nil] # None
|
71
|
+
Types::Maybe::Coercible::Float['12.3'] # Some(12.3)
|
72
|
+
|
73
|
+
# 'Maybe' types can also accessed by calling '.maybe' on a regular type:
|
74
|
+
Types::Strict::Integer.maybe # equivalent to Types::Maybe::Strict::Integer
|
75
|
+
```
|
76
|
+
|
77
|
+
You can define your own optional types:
|
78
|
+
|
79
|
+
``` ruby
|
80
|
+
maybe_string = Types::Strict::String.maybe
|
81
|
+
|
82
|
+
maybe_string[nil]
|
83
|
+
# => None
|
84
|
+
|
85
|
+
maybe_string[nil].fmap(&:upcase)
|
86
|
+
# => None
|
87
|
+
|
88
|
+
maybe_string['something']
|
89
|
+
# => Some('something')
|
90
|
+
|
91
|
+
maybe_string['something'].fmap(&:upcase)
|
92
|
+
# => Some('SOMETHING')
|
93
|
+
|
94
|
+
maybe_string['something'].fmap(&:upcase).value_or('NOTHING')
|
95
|
+
# => "SOMETHING"
|
96
|
+
```
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
title: Sum
|
3
|
+
layout: gem-single
|
4
|
+
name: dry-types
|
5
|
+
order: 7
|
6
|
+
---
|
7
|
+
|
8
|
+
You can specify sum types using `|` operator, it is an explicit way of defining what the valid types of a value are.
|
9
|
+
|
10
|
+
For example `dry-types` defines the `Bool` type which is a sum consisting of the `True` and `False` types, expressed as `Types::True | Types::False`.
|
11
|
+
|
12
|
+
Another common case is defining that something can be either `nil` or something else:
|
13
|
+
|
14
|
+
``` ruby
|
15
|
+
nil_or_string = Types::Nil | Types::String
|
16
|
+
|
17
|
+
nil_or_string[nil] # => nil
|
18
|
+
nil_or_string["hello"] # => "hello"
|
19
|
+
|
20
|
+
nil_or_string[123] # raises Dry::Types::ConstraintError
|
21
|
+
```
|
data/dry-types.gemspec
CHANGED
@@ -1,47 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path('
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require 'dry/types/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = 'dry-types'
|
9
9
|
spec.version = Dry::Types::VERSION.dup
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
10
|
+
spec.authors = ['Piotr Solnica']
|
11
|
+
spec.email = ['piotr.solnica@gmail.com']
|
12
12
|
spec.license = 'MIT'
|
13
13
|
|
14
14
|
spec.summary = 'Type system for Ruby supporting coercions, constraints and complex types like structs, value objects, enums etc.'
|
15
15
|
spec.description = spec.summary
|
16
|
-
spec.homepage =
|
16
|
+
spec.homepage = 'https://github.com/dry-rb/dry-types'
|
17
17
|
|
18
18
|
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
19
19
|
# delete this section to allow pushing this gem to any host.
|
20
20
|
if spec.respond_to?(:metadata)
|
21
|
-
spec.metadata['allowed_push_host'] =
|
22
|
-
spec.metadata['changelog_uri'] =
|
23
|
-
spec.metadata['source_code_uri'] =
|
24
|
-
spec.metadata['bug_tracker_uri'] =
|
21
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
22
|
+
spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md'
|
23
|
+
spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-types'
|
24
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-types/issues'
|
25
25
|
else
|
26
|
-
raise
|
26
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
27
27
|
end
|
28
28
|
|
29
29
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - ['bin/console', 'bin/setup']
|
30
|
-
spec.bindir =
|
30
|
+
spec.bindir = 'exe'
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
|
-
spec.require_paths = [
|
33
|
-
spec.required_ruby_version =
|
32
|
+
spec.require_paths = ['lib']
|
33
|
+
spec.required_ruby_version = '>= 2.4.0'
|
34
34
|
|
35
35
|
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
36
|
-
spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
|
37
|
-
spec.add_runtime_dependency 'dry-inflector', '~> 0.1', '>= 0.1.2'
|
38
36
|
spec.add_runtime_dependency 'dry-container', '~> 0.3'
|
37
|
+
spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
|
39
38
|
spec.add_runtime_dependency 'dry-equalizer', '~> 0.2', '>= 0.2.2'
|
40
|
-
spec.add_runtime_dependency 'dry-
|
39
|
+
spec.add_runtime_dependency 'dry-inflector', '~> 0.1', '>= 0.1.2'
|
40
|
+
spec.add_runtime_dependency 'dry-logic', '~> 1.0', '>= 1.0.2'
|
41
41
|
|
42
|
-
spec.add_development_dependency
|
43
|
-
spec.add_development_dependency "rake", "~> 11.0"
|
44
|
-
spec.add_development_dependency "rspec", "~> 3.3"
|
42
|
+
spec.add_development_dependency 'bundler'
|
45
43
|
spec.add_development_dependency 'dry-monads', '~> 0.2'
|
44
|
+
spec.add_development_dependency 'rake', '~> 11.0'
|
45
|
+
spec.add_development_dependency 'rspec', '~> 3.3'
|
46
46
|
spec.add_development_dependency 'yard', '~> 0.9.5'
|
47
47
|
end
|
data/lib/dry/types.rb
CHANGED
@@ -33,7 +33,7 @@ module Dry
|
|
33
33
|
extend Dry::Core::Deprecations[:'dry-types']
|
34
34
|
include Dry::Core::Constants
|
35
35
|
|
36
|
-
TYPE_SPEC_REGEX =
|
36
|
+
TYPE_SPEC_REGEX = /(.+)<(.+)>/.freeze
|
37
37
|
|
38
38
|
# @see Dry.Types
|
39
39
|
def self.module(*namespaces, default: :nominal, **aliases)
|
@@ -45,7 +45,7 @@ module Dry
|
|
45
45
|
|
46
46
|
# @api private
|
47
47
|
def self.included(*)
|
48
|
-
raise
|
48
|
+
raise 'Import Dry.Types, not Dry::Types'
|
49
49
|
end
|
50
50
|
|
51
51
|
# Return container with registered built-in type objects
|
@@ -89,7 +89,7 @@ module Dry
|
|
89
89
|
def self.[](name)
|
90
90
|
type_map.fetch_or_store(name) do
|
91
91
|
case name
|
92
|
-
when String
|
92
|
+
when ::String
|
93
93
|
result = name.match(TYPE_SPEC_REGEX)
|
94
94
|
|
95
95
|
if result
|
@@ -98,7 +98,12 @@ module Dry
|
|
98
98
|
else
|
99
99
|
container[name]
|
100
100
|
end
|
101
|
-
when Class
|
101
|
+
when ::Class
|
102
|
+
warn(<<~DEPRECATION)
|
103
|
+
Using Dry::Types.[] with a class is deprecated, please use string identifiers: Dry::Types[Integer] -> Dry::Types['integer'].
|
104
|
+
If you're using dry-struct this means changing `attribute :counter, Integer` to `attribute :counter, Dry::Types['integer']` or to `attribute :counter, 'integer'`.
|
105
|
+
DEPRECATION
|
106
|
+
|
102
107
|
type_name = identifier(name)
|
103
108
|
|
104
109
|
if container.key?(type_name)
|
data/lib/dry/types/array.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/types/array/member'
|
4
|
+
require 'dry/types/array/constructor'
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module Types
|
@@ -24,6 +25,11 @@ module Dry
|
|
24
25
|
|
25
26
|
Array::Member.new(primitive, **options, member: member)
|
26
27
|
end
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
def constructor_type
|
31
|
+
::Dry::Types::Array::Constructor
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/types/constructor'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Types
|
7
|
+
# @api public
|
8
|
+
class Array < Nominal
|
9
|
+
# @api private
|
10
|
+
class Constructor < ::Dry::Types::Constructor
|
11
|
+
# @api private
|
12
|
+
def constructor_type
|
13
|
+
::Dry::Types::Array::Constructor
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Lax]
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def lax
|
20
|
+
Lax.new(type.lax.constructor(fn, meta: meta))
|
21
|
+
end
|
22
|
+
|
23
|
+
# @see Dry::Types::Array#of
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
def of(member)
|
27
|
+
type.of(member).constructor(fn, meta: meta)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|