sorbet-coerce 0.2.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5eefb63dc137b65889fa5dd16b05fcf3bef550474d7f7f175746ccca96e640d
4
- data.tar.gz: 0ca052e76b580d9979d24444b8bee8d564a49c6d2162acd36469fbd205cb6354
3
+ metadata.gz: 1a6067fb52161543309158003029c02c354f0c88d6dada780973141b4c7f3ca5
4
+ data.tar.gz: 15e371a34bdbb450ffa5a24f6f235d4f67f7b6964c1819a81286d60f687f2d66
5
5
  SHA512:
6
- metadata.gz: afb06e4b35972579d9ff0ffb0d9eb48c1de7465911b0f56a07a1d7dcda528f70d525834f5ac81c300394132ae5e8fec7d614814c900710778fa13296ed2db7f3
7
- data.tar.gz: eecba6f2089a944984b2e6ba595ad21bbff2d11bb3fc56d38532fff94f029fe6beac3e1fce25272d46162e893d3040a548fe4240058db8a258900ee815acb946
6
+ metadata.gz: f0000b0124391cb0432486aaa4193442bb5adfd3ff67552bb6671a38ea4709f9c81b850355b838e00f6dda72f5d207f117b694dee1f78eb9f4d2805af7cad55d
7
+ data.tar.gz: 1ac80f3aad685c57123d4acd67178385a0068190676c4446d4bc6c99945e8313ea67b09e2a40958fc7e08778d8811a969e0467b46ed5071fc80d5aafa429de75
@@ -0,0 +1,17 @@
1
+ # typed: true
2
+ module SafeType
3
+ class CoercionError < StandardError; end
4
+ end
5
+
6
+ module TypeCoerce
7
+ extend T::Sig
8
+ extend T::Generic
9
+
10
+ Elem = type_member
11
+
12
+ sig { params(args: T.untyped, raise_coercion_error: T.nilable(T::Boolean)).returns(Elem) }
13
+ def from(args, raise_coercion_error: nil); end
14
+
15
+ class CoercionError < SafeType::CoercionError; end
16
+ class ShapeError < SafeType::CoercionError; end
17
+ end
data/lib/sorbet-coerce.rb CHANGED
@@ -1,19 +1,19 @@
1
1
  # typed: strict
2
- require_relative 'configuration'
3
- require 'private/converter'
2
+ require 'sorbet-coerce/configuration'
3
+ require 'sorbet-coerce/converter'
4
4
  require 'safe_type'
5
5
 
6
- module T::Coerce
6
+ module TypeCoerce
7
7
  class CoercionError < SafeType::CoercionError; end
8
8
  class ShapeError < SafeType::CoercionError; end
9
9
 
10
10
  define_singleton_method(:[]) do |type|
11
- Class.new(T::Private::Converter) do
11
+ Class.new(TypeCoerce::Private::Converter) do
12
12
  define_method(:to_s) { "#{name}#[#{type.to_s}]" }
13
13
 
14
14
  define_method(:from) do |args, raise_coercion_error: nil|
15
15
  if raise_coercion_error.nil?
16
- raise_coercion_error = T::Coerce::Configuration.raise_coercion_error
16
+ raise_coercion_error = TypeCoerce::Configuration.raise_coercion_error
17
17
  end
18
18
 
19
19
  T.send('let', send('_convert', args, type, raise_coercion_error), type)
@@ -1,7 +1,7 @@
1
1
  # typed: true
2
2
  require 'sorbet-runtime'
3
3
 
4
- module T::Coerce
4
+ module TypeCoerce
5
5
  module Configuration
6
6
  class << self
7
7
  extend T::Sig
@@ -12,4 +12,4 @@ module T::Coerce
12
12
  end
13
13
  end
14
14
 
15
- T::Coerce::Configuration.raise_coercion_error = true
15
+ TypeCoerce::Configuration.raise_coercion_error = true
@@ -1,11 +1,14 @@
1
1
  # typed: strict
2
2
  require 'safe_type'
3
+ require 'set'
3
4
  require 'sorbet-runtime'
4
5
  require 'polyfill'
5
6
 
6
7
  using Polyfill(Hash: %w[#slice])
7
8
 
8
- module T::Private
9
+ module TypeCoerce; end
10
+
11
+ module TypeCoerce::Private
9
12
  class Converter
10
13
  extend T::Sig
11
14
 
@@ -22,8 +25,12 @@ module T::Private
22
25
  protected
23
26
  sig { params(value: T.untyped, type: T.untyped, raise_coercion_error: T::Boolean).returns(T.untyped) }
24
27
  def _convert(value, type, raise_coercion_error)
25
- if type.is_a?(T::Types::TypedArray)
28
+ if type.is_a?(T::Types::Untyped)
29
+ value
30
+ elsif type.is_a?(T::Types::TypedArray)
26
31
  _convert_to_a(value, type.type, raise_coercion_error)
32
+ elsif type.is_a?(T::Types::TypedSet)
33
+ Set.new(_convert_to_a(value, type.type, raise_coercion_error))
27
34
  elsif type.is_a?(T::Types::Simple)
28
35
  _convert(value, type.raw_type, raise_coercion_error)
29
36
  elsif type.is_a?(T::Types::Union)
@@ -51,10 +58,23 @@ module T::Private
51
58
  else
52
59
  _convert(value, type.types[nil_idx == 0 ? 1 : 0], raise_coercion_error)
53
60
  end
61
+ elsif type.is_a?(T::Types::TypedHash)
62
+ return {} if _nil_like?(value, type)
63
+
64
+ unless value.respond_to?(:map)
65
+ raise TypeCoerce::ShapeError.new(value, type)
66
+ end
67
+
68
+ value.map do |k, v|
69
+ [
70
+ _convert(k, type.keys, raise_coercion_error),
71
+ _convert(v, type.values, raise_coercion_error),
72
+ ]
73
+ end.to_h
54
74
  elsif Object.const_defined?('T::Private::Types::TypeAlias') &&
55
75
  type.is_a?(T::Private::Types::TypeAlias)
56
76
  _convert(value, type.aliased_type, raise_coercion_error)
57
- elsif type < T::Struct
77
+ elsif type.respond_to?(:<) && type < T::Struct
58
78
  args = _build_args(value, type, raise_coercion_error)
59
79
  type.new(args)
60
80
  else
@@ -77,15 +97,18 @@ module T::Private
77
97
  else
78
98
  safe_type_rule = type
79
99
  end
80
- SafeType::coerce(value, safe_type_rule)
100
+
101
+ if safe_type_rule.is_a?(SafeType::Rule)
102
+ SafeType::coerce(value, safe_type_rule)
103
+ else
104
+ type.new(value)
105
+ end
81
106
  rescue SafeType::EmptyValueError, SafeType::CoercionError
82
107
  if raise_coercion_error
83
- raise T::Coerce::CoercionError.new(value, type)
108
+ raise TypeCoerce::CoercionError.new(value, type)
84
109
  else
85
110
  nil
86
111
  end
87
- rescue SafeType::InvalidRuleError
88
- type.new(value)
89
112
  end
90
113
 
91
114
  sig { params(ary: T.untyped, type: T.untyped, raise_coercion_error: T::Boolean).returns(T.untyped) }
@@ -93,7 +116,7 @@ module T::Private
93
116
  return [] if _nil_like?(ary, type)
94
117
 
95
118
  unless ary.respond_to?(:map)
96
- raise T::Coerce::ShapeError.new(ary, type)
119
+ raise TypeCoerce::ShapeError.new(ary, type)
97
120
  end
98
121
 
99
122
  ary.map { |value| _convert(value, type, raise_coercion_error) }
@@ -104,7 +127,7 @@ module T::Private
104
127
  return {} if _nil_like?(args, Hash)
105
128
 
106
129
  unless args.respond_to?(:each_pair)
107
- raise T::Coerce::ShapeError.new(args, type)
130
+ raise TypeCoerce::ShapeError.new(args, type)
108
131
  end
109
132
 
110
133
  props = type.props
@@ -0,0 +1,10 @@
1
+ # typed: true
2
+ module T
3
+ module Private
4
+ module Types
5
+ class TypeAlias
6
+ def aliased_type; end
7
+ end
8
+ end
9
+ end
10
+ end
data/spec/coerce_spec.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  require 'sorbet-coerce'
3
3
  require 'sorbet-runtime'
4
4
 
5
- describe T::Coerce do
5
+ describe TypeCoerce do
6
6
  context 'when given T::Struct' do
7
7
  class ParamInfo < T::Struct
8
8
  const :name, String
@@ -27,6 +27,14 @@ describe T::Coerce do
27
27
  const :a, Integer, default: 1
28
28
  end
29
29
 
30
+ class HashParams < T::Struct
31
+ const :myhash, T::Hash[String, Integer]
32
+ end
33
+
34
+ class HashParamsWithDefault < T::Struct
35
+ const :myhash, T::Hash[String, Integer], default: Hash['a' => 1]
36
+ end
37
+
30
38
  class CustomType
31
39
  attr_reader :a
32
40
 
@@ -44,7 +52,7 @@ describe T::Coerce do
44
52
  end
45
53
 
46
54
  let!(:param) {
47
- T::Coerce[Param].new.from({
55
+ TypeCoerce[Param].new.from({
48
56
  id: 1,
49
57
  info: {
50
58
  name: 'mango',
@@ -60,7 +68,7 @@ describe T::Coerce do
60
68
  }
61
69
 
62
70
  let!(:param2) {
63
- T::Coerce[Param].new.from({
71
+ TypeCoerce[Param].new.from({
64
72
  id: '2',
65
73
  info: {
66
74
  name: 'honeydew',
@@ -101,7 +109,7 @@ describe T::Coerce do
101
109
  expect(param2.opt.notes).to eql []
102
110
 
103
111
  expect {
104
- T::Coerce[Param].new.from({
112
+ TypeCoerce[Param].new.from({
105
113
  id: 3,
106
114
  info: {
107
115
  # missing required name
@@ -110,8 +118,8 @@ describe T::Coerce do
110
118
  })
111
119
  }.to raise_error(ArgumentError)
112
120
 
113
- expect(T::Coerce[DefaultParams].new.from(nil).a).to be 1
114
- expect(T::Coerce[DefaultParams].new.from('').a).to be 1
121
+ expect(TypeCoerce[DefaultParams].new.from(nil).a).to be 1
122
+ expect(TypeCoerce[DefaultParams].new.from('').a).to be 1
115
123
  end
116
124
  end
117
125
 
@@ -123,76 +131,130 @@ describe T::Coerce do
123
131
 
124
132
  it 'raises an error' do
125
133
  expect {
126
- T::Coerce[Param2].new.from({id: 1, info: 1})
134
+ TypeCoerce[Param2].new.from({id: 1, info: 1})
127
135
  }.to raise_error(ArgumentError)
128
136
  end
129
137
  end
130
138
 
131
139
  context 'when given primitive types' do
132
140
  it 'reveals the right type' do
133
- T.assert_type!(T::Coerce[Integer].new.from(1), Integer)
134
- T.assert_type!(T::Coerce[Integer].new.from('1.0'), Integer)
135
- T.assert_type!(T::Coerce[T.nilable(Integer)].new.from(nil), T.nilable(Integer))
141
+ T.assert_type!(TypeCoerce[Integer].new.from(1), Integer)
142
+ T.assert_type!(TypeCoerce[Integer].new.from('1.0'), Integer)
143
+ T.assert_type!(TypeCoerce[T.nilable(Integer)].new.from(nil), T.nilable(Integer))
136
144
  end
137
145
 
138
146
  it 'coreces correctly' do
139
- expect{T::Coerce[Integer].new.from(nil)}.to raise_error(TypeError)
140
- expect(T::Coerce[T.nilable(Integer)].new.from(nil) || 1).to eql 1
141
- expect(T::Coerce[Integer].new.from(2)).to eql 2
142
- expect(T::Coerce[Integer].new.from('1.0')).to eql 1
147
+ expect{TypeCoerce[Integer].new.from(nil)}.to raise_error(TypeError)
148
+ expect(TypeCoerce[T.nilable(Integer)].new.from(nil) || 1).to eql 1
149
+ expect(TypeCoerce[Integer].new.from(2)).to eql 2
150
+ expect(TypeCoerce[Integer].new.from('1.0')).to eql 1
143
151
 
144
- expect{T::Coerce[T.nilable(Integer)].new.from('invalid integer string')}.to raise_error(T::Coerce::CoercionError)
145
- expect(T::Coerce[Float].new.from('1.0')).to eql 1.0
152
+ expect{TypeCoerce[T.nilable(Integer)].new.from('invalid integer string')}.to raise_error(TypeCoerce::CoercionError)
153
+ expect(TypeCoerce[Float].new.from('1.0')).to eql 1.0
146
154
 
147
- expect(T::Coerce[T::Boolean].new.from('false')).to be false
148
- expect(T::Coerce[T::Boolean].new.from('true')).to be true
155
+ expect(TypeCoerce[T::Boolean].new.from('false')).to be false
156
+ expect(TypeCoerce[T::Boolean].new.from('true')).to be true
149
157
 
150
- expect(T::Coerce[T.nilable(Integer)].new.from('')).to be nil
151
- expect{T::Coerce[T.nilable(Integer)].new.from([])}.to raise_error(T::Coerce::CoercionError)
152
- expect(T::Coerce[T.nilable(String)].new.from('')).to eql ''
158
+ expect(TypeCoerce[T.nilable(Integer)].new.from('')).to be nil
159
+ expect{TypeCoerce[T.nilable(Integer)].new.from([])}.to raise_error(TypeCoerce::CoercionError)
160
+ expect(TypeCoerce[T.nilable(String)].new.from('')).to eql ''
153
161
  end
154
162
  end
155
163
 
156
164
  context 'when given custom types' do
157
165
  it 'coerces correctly' do
158
- T.assert_type!(T::Coerce[CustomType].new.from(a: 1), CustomType)
159
- expect(T::Coerce[CustomType].new.from(1).a).to be 1
166
+ T.assert_type!(TypeCoerce[CustomType].new.from(a: 1), CustomType)
167
+ expect(TypeCoerce[CustomType].new.from(1).a).to be 1
160
168
 
161
- expect{T::Coerce[UnsupportedCustomType].new.from(1)}.to raise_error(ArgumentError)
169
+ expect{TypeCoerce[UnsupportedCustomType].new.from(1)}.to raise_error(ArgumentError)
162
170
  # CustomType2.new(anything) returns Integer 1; 1.is_a?(CustomType2) == false
163
- expect{T::Coerce[CustomType2].new.from(1)}.to raise_error(TypeError)
171
+ expect{TypeCoerce[CustomType2].new.from(1)}.to raise_error(TypeError)
164
172
  end
165
173
  end
166
174
 
167
175
  context 'when dealing with arries' do
168
176
  it 'coreces correctly' do
169
- expect(T::Coerce[T::Array[Integer]].new.from(nil)).to eql []
170
- expect(T::Coerce[T::Array[Integer]].new.from('')).to eql []
171
- expect{T::Coerce[T::Array[Integer]].new.from('not an array')}.to raise_error(T::Coerce::ShapeError)
172
- expect{T::Coerce[T::Array[Integer]].new.from('1')}.to raise_error(T::Coerce::ShapeError)
173
- expect(T::Coerce[T::Array[Integer]].new.from(['1', '2', '3'])).to eql [1, 2, 3]
174
- expect{T::Coerce[T::Array[Integer]].new.from(['1', 'invalid', '3'])}.to raise_error(T::Coerce::CoercionError)
175
- expect{T::Coerce[T::Array[Integer]].new.from({a: 1})}.to raise_error(T::Coerce::CoercionError)
176
-
177
- infos = T::Coerce[T::Array[ParamInfo]].new.from([{name: 'a', skill_ids: []}])
177
+ expect(TypeCoerce[T::Array[Integer]].new.from(nil)).to eql []
178
+ expect(TypeCoerce[T::Array[Integer]].new.from('')).to eql []
179
+ expect{TypeCoerce[T::Array[Integer]].new.from('not an array')}.to raise_error(TypeCoerce::ShapeError)
180
+ expect{TypeCoerce[T::Array[Integer]].new.from('1')}.to raise_error(TypeCoerce::ShapeError)
181
+ expect(TypeCoerce[T::Array[Integer]].new.from(['1', '2', '3'])).to eql [1, 2, 3]
182
+ expect{TypeCoerce[T::Array[Integer]].new.from(['1', 'invalid', '3'])}.to raise_error(TypeCoerce::CoercionError)
183
+ expect{TypeCoerce[T::Array[Integer]].new.from({a: 1})}.to raise_error(TypeCoerce::CoercionError)
184
+
185
+ infos = TypeCoerce[T::Array[ParamInfo]].new.from([{name: 'a', skill_ids: []}])
178
186
  T.assert_type!(infos, T::Array[ParamInfo])
179
187
  expect(infos.first.name).to eql 'a'
180
188
 
181
- infos = T::Coerce[T::Array[ParamInfo]].new.from([{name: 'b', skill_ids: []}])
189
+ infos = TypeCoerce[T::Array[ParamInfo]].new.from([{name: 'b', skill_ids: []}])
182
190
  T.assert_type!(infos, T::Array[ParamInfo])
183
191
  expect(infos.first.name).to eql 'b'
184
192
 
185
193
  expect {
186
- T::Coerce[ParamInfo2].new.from({a: nil, b: nil})
194
+ TypeCoerce[ParamInfo2].new.from({a: nil, b: nil})
187
195
  }.to raise_error(TypeError)
188
196
  end
189
197
  end
190
198
 
199
+ context 'when dealing with hashes' do
200
+ it 'coreces correctly' do
201
+ expect(TypeCoerce[T::Hash[T.untyped, T.untyped]].new.from(nil)).to eql({})
202
+
203
+ expect(TypeCoerce[T::Hash[String, T::Boolean]].new.from({
204
+ a: 'true',
205
+ b: 'false',
206
+ })).to eql({
207
+ 'a' => true,
208
+ 'b' => false,
209
+ })
210
+
211
+ expect(TypeCoerce[HashParams].new.from({
212
+ myhash: {'a' => '1', 'b' => '2'},
213
+ }).myhash).to eql({'a' => 1, 'b' => 2})
214
+
215
+ expect(TypeCoerce[HashParamsWithDefault].new.from({}).myhash).to eql({'a' => 1})
216
+
217
+ expect {
218
+ TypeCoerce[T::Hash[String, T::Boolean]].new.from({
219
+ a: 'invalid',
220
+ b: 'false',
221
+ })
222
+ }.to raise_error(TypeCoerce::CoercionError)
223
+
224
+ expect {
225
+ TypeCoerce[T::Hash[String, Integer]].new.from(1)
226
+ }.to raise_error(TypeCoerce::ShapeError)
227
+ end
228
+ end
229
+
230
+ context 'when dealing with sets' do
231
+ it 'coreces correctly' do
232
+ expect(TypeCoerce[T::Set[Integer]].new.from(
233
+ Set.new(['1', '2', '3'])
234
+ )).to eq Set.new([1, 2, 3])
235
+
236
+ expect {
237
+ TypeCoerce[T::Set[Integer]].new.from(Set.new(['1', 'invalid', '3']))
238
+ }.to raise_error(TypeCoerce::CoercionError)
239
+
240
+ expect {
241
+ TypeCoerce[T::Set[Integer]].new.from(1)
242
+ }.to raise_error(TypeCoerce::ShapeError)
243
+ end
244
+ end
245
+
191
246
  context 'when given a type alias' do
192
247
  MyType = T.type_alias(T::Boolean)
193
248
 
194
249
  it 'coerces correctly' do
195
- expect(T::Coerce[MyType].new.from('false')).to be false
250
+ expect(TypeCoerce[MyType].new.from('false')).to be false
196
251
  end
197
252
  end
253
+
254
+ it 'works with T.untyped' do
255
+ expect(TypeCoerce[T.untyped].new.from(1)).to eql 1
256
+
257
+ obj = CustomType.new(1)
258
+ expect(TypeCoerce[T::Hash[String, T.untyped]].new.from({a: obj})).to eq({'a' => obj})
259
+ end
198
260
  end
data/spec/nested_spec.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  require 'sorbet-coerce'
3
3
  require 'sorbet-runtime'
4
4
 
5
- describe T::Coerce do
5
+ describe TypeCoerce do
6
6
  context 'when given nested types' do
7
7
  class User < T::Struct
8
8
  const :id, Integer
@@ -15,7 +15,7 @@ describe T::Coerce do
15
15
  end
16
16
 
17
17
  it 'works with nest T::Struct' do
18
- converted = T::Coerce[NestedParam].new.from({
18
+ converted = TypeCoerce[NestedParam].new.from({
19
19
  users: [{id: '1'}],
20
20
  params: {
21
21
  users: [{id: '2', valid: 'true'}],
@@ -42,16 +42,16 @@ describe T::Coerce do
42
42
 
43
43
  it 'works with nest T::Array' do
44
44
  expect {
45
- T::Coerce[T::Array[T.nilable(Integer)]].new.from(['1', 'invalid', '3'])
46
- }.to raise_error(T::Coerce::CoercionError)
45
+ TypeCoerce[T::Array[T.nilable(Integer)]].new.from(['1', 'invalid', '3'])
46
+ }.to raise_error(TypeCoerce::CoercionError)
47
47
  expect(
48
- T::Coerce[T::Array[T::Array[Integer]]].new.from([nil])
48
+ TypeCoerce[T::Array[T::Array[Integer]]].new.from([nil])
49
49
  ).to eql([[]])
50
50
  expect(
51
- T::Coerce[T::Array[T::Array[Integer]]].new.from([['1'], ['2'], ['3']]),
51
+ TypeCoerce[T::Array[T::Array[Integer]]].new.from([['1'], ['2'], ['3']]),
52
52
  ).to eql [[1], [2], [3]]
53
53
 
54
- expect(T::Coerce[
54
+ expect(TypeCoerce[
55
55
  T::Array[
56
56
  T::Array[
57
57
  T::Array[User]
@@ -59,7 +59,7 @@ describe T::Coerce do
59
59
  ]
60
60
  ].new.from([[[{id: '1'}]]]).flatten.first.id).to eql(1)
61
61
 
62
- expect(T::Coerce[
62
+ expect(TypeCoerce[
63
63
  T::Array[
64
64
  T::Array[
65
65
  T::Array[
@@ -71,9 +71,18 @@ describe T::Coerce do
71
71
  ]
72
72
  ].new.from([[[[[{id: 1}]]]]]).flatten.first.id).to eql 1
73
73
 
74
- expect(T::Coerce[
74
+ expect(TypeCoerce[
75
75
  T.nilable(T::Array[T.nilable(T::Array[T.nilable(User)])])
76
76
  ].new.from([[{id: '1'}]]).flatten.map(&:id)).to eql([1])
77
77
  end
78
+
79
+ it 'works with nested T::Hash' do
80
+ expect(
81
+ TypeCoerce[T::Hash[Symbol, T::Hash[Symbol, Integer]]].new.from({
82
+ a: nil,
83
+ b: {c: '1'}
84
+ })
85
+ ).to eql({a: {}, b: {c: 1}})
86
+ end
78
87
  end
79
88
  end
@@ -2,12 +2,12 @@
2
2
  require 'sorbet-coerce'
3
3
  require 'sorbet-runtime'
4
4
 
5
- describe T::Coerce do
5
+ describe TypeCoerce do
6
6
  context 'when type errors are soft errors' do
7
7
  let(:ignore_error) { Proc.new {} }
8
8
 
9
9
  before(:each) do
10
- allow(T::Coerce::Configuration).to receive(
10
+ allow(TypeCoerce::Configuration).to receive(
11
11
  :raise_coercion_error,
12
12
  ).and_return(false)
13
13
 
@@ -42,24 +42,24 @@ describe T::Coerce do
42
42
 
43
43
  it 'overwrites the global config when inline config is set' do
44
44
  expect {
45
- T::Coerce[Integer].new.from(invalid_arg, raise_coercion_error: true)
46
- }.to raise_error(T::Coerce::CoercionError)
45
+ TypeCoerce[Integer].new.from(invalid_arg, raise_coercion_error: true)
46
+ }.to raise_error(TypeCoerce::CoercionError)
47
47
  end
48
48
 
49
49
  it 'works as expected' do
50
- expect(T::Coerce[Integer].new.from(invalid_arg)).to eql(nil)
50
+ expect(TypeCoerce[Integer].new.from(invalid_arg)).to eql(nil)
51
51
 
52
- expect{T::Coerce[T::Array[Integer]].new.from(1)}.to raise_error(T::Coerce::ShapeError)
53
- expect(T::Coerce[T::Array[Integer]].new.from({a: 1})).to eql([nil])
52
+ expect{TypeCoerce[T::Array[Integer]].new.from(1)}.to raise_error(TypeCoerce::ShapeError)
53
+ expect(TypeCoerce[T::Array[Integer]].new.from({a: 1})).to eql([nil])
54
54
 
55
55
  expect {
56
- T::Coerce[CustomTypeRaisesHardError].new.from(1)
56
+ TypeCoerce[CustomTypeRaisesHardError].new.from(1)
57
57
  }.to raise_error(StandardError)
58
- expect(T::Coerce[CustomTypeDoesNotRiaseHardError].new.from(1)).to eql(1)
58
+ expect(TypeCoerce[CustomTypeDoesNotRiaseHardError].new.from(1)).to eql(1)
59
59
 
60
60
  sorbet_version = Gem.loaded_specs['sorbet-runtime'].version
61
61
  if sorbet_version >= Gem::Version.new('0.4.4948')
62
- expect(T::Coerce[ParamsWithSortError].new.from({a: invalid_arg}).a).to eql(nil)
62
+ expect(TypeCoerce[ParamsWithSortError].new.from({a: invalid_arg}).a).to eql(nil)
63
63
  end
64
64
  end
65
65
  end
@@ -0,0 +1,22 @@
1
+ # typed: true
2
+ require 'sorbet-coerce'
3
+
4
+ T.assert_type!(TypeCoerce[Integer].new.from('1'), Integer)
5
+ T.assert_type!(
6
+ TypeCoerce[T.nilable(Integer)].new.from('invalid', raise_coercion_error: false),
7
+ T.nilable(Integer),
8
+ )
9
+
10
+ TypeCoerce::Configuration.raise_coercion_error = true
11
+ coercion_error = nil
12
+ begin
13
+ TypeCoerce[T.nilable(Integer)].new.from('invalid')
14
+ rescue TypeCoerce::CoercionError => e
15
+ coercion_error = e
16
+ end
17
+ raise 'no coercion error is raised' unless coercion_error
18
+
19
+ T.assert_type!(
20
+ TypeCoerce[T.nilable(Integer)].new.from('invalid', raise_coercion_error: false),
21
+ T.nilable(Integer),
22
+ )
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-coerce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chan Zuckerberg Initiative
@@ -118,13 +118,15 @@ executables: []
118
118
  extensions: []
119
119
  extra_rdoc_files: []
120
120
  files:
121
- - lib/configuration.rb
122
- - lib/private/converter.rb
121
+ - lib/bundled_rbi/sorbet-coerce.rbi
123
122
  - lib/sorbet-coerce.rb
124
- - rbi/sorbet-coerce.rbi
123
+ - lib/sorbet-coerce/configuration.rb
124
+ - lib/sorbet-coerce/converter.rb
125
+ - lib/sorbet-coerce/coverter.rbi
125
126
  - spec/coerce_spec.rb
126
127
  - spec/nested_spec.rb
127
128
  - spec/soft_error_spec.rb
129
+ - spec/sorbet_test_cases.rb
128
130
  - spec/spec_helper.rb
129
131
  homepage: https://github.com/chanzuckerberg/sorbet-coerce
130
132
  licenses:
@@ -1,20 +0,0 @@
1
- # typed: true
2
- module T
3
- module Coerce
4
- extend T::Sig
5
- extend T::Generic
6
-
7
- Elem = type_member
8
-
9
- sig { params(args: T.untyped, raise_value_error: T.nilable(T::Boolean)).returns(Elem) }
10
- def from(args, raise_value_error: nil); end
11
- end
12
-
13
- module Private
14
- module Types
15
- class TypeAlias
16
- def aliased_type; end
17
- end
18
- end
19
- end
20
- end