Class: T::Types::Union
Overview
Takes a list of types. Validates that an object matches at least one of the types.
Direct Known Subclasses
Defined Under Namespace
Modules: Private
Instance Method Summary collapse
- #build_type ⇒ Object
-
#initialize(types) ⇒ Union
constructor
Don’t use Union.new directly, use ‘Private::Pool.union_of_types` inside sorbet-runtime and `T.any` elsewhere.
-
#name ⇒ Object
overrides Base.
-
#recursively_valid?(obj) ⇒ Boolean
overrides Base.
- #types ⇒ Object
- #unwrap_nilable ⇒ Object
-
#valid?(obj) ⇒ Boolean
overrides Base.
Methods inherited from Base
#==, #describe_obj, #error_message_for_obj, #error_message_for_obj_recursive, #hash, method_added, #subtype_of?, #to_s, #validate!
Constructor Details
#initialize(types) ⇒ Union
Don’t use Union.new directly, use ‘Private::Pool.union_of_types` inside sorbet-runtime and `T.any` elsewhere.
9 10 11 |
# File 'lib/types/types/union.rb', line 9 def initialize(types) @inner_types = types end |
Instance Method Details
#build_type ⇒ Object
40 41 42 43 |
# File 'lib/types/types/union.rb', line 40 def build_type types nil end |
#name ⇒ Object
overrides Base
46 47 48 49 |
# File 'lib/types/types/union.rb', line 46 def name # Use the attr_reader here so we can override it in SimplePairUnion type_shortcuts(types) end |
#recursively_valid?(obj) ⇒ Boolean
overrides Base
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/types/types/union.rb', line 75 def recursively_valid?(obj) member_modules = @member_modules if member_modules.nil? # Force the lazy types builder, which also computes @member_modules types member_modules = @member_modules end index = 0 if member_modules # For an all-Simple union, recursively_valid? and valid? coincide # (Simple's recursively_valid? is exactly `obj.is_a?(raw_type)`). while index < member_modules.length return true if obj.is_a?(member_modules[index]) index += 1 end else members = types while index < members.length return true if members.fetch(index).recursively_valid?(obj) index += 1 end end false end |
#types ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/types/types/union.rb', line 13 def types @types ||= begin flattened = @inner_types.flat_map do |type| type = T::Utils.coerce(type) if type.is_a?(Union) # Simplify nested unions (mostly so `name` returns a nicer value) type.types else type end end.uniq # When every member is a plain Simple (whose valid? is exactly # `obj.is_a?(raw_type)`), precompute the members' raw modules so # valid? can skip per-member dispatch. instance_of? (the is_a? only # narrows for static checking) so that any Simple subclass overriding # valid? would be excluded. Note this snapshots the members at build # time. member_modules = [] all_simple = flattened.all? do |type| type.is_a?(T::Types::Simple) && type.instance_of?(T::Types::Simple) && member_modules << type.raw_type end @member_modules = all_simple ? member_modules.freeze : false flattened end end |
#unwrap_nilable ⇒ Object
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/types/types/union.rb', line 129 def unwrap_nilable non_nil_types = types.reject { |t| t == T::Utils::Nilable::NIL_TYPE } return nil if types.length == non_nil_types.length case non_nil_types.length when 0 then nil when 1 then non_nil_types.first else T::Types::Union::Private::Pool.union_of_types(non_nil_types[0], non_nil_types[1], non_nil_types[2..-1]) end end |
#valid?(obj) ⇒ Boolean
overrides Base
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/types/types/union.rb', line 101 def valid?(obj) member_modules = @member_modules if member_modules.nil? # Force the lazy types builder, which also computes @member_modules types member_modules = @member_modules end index = 0 if member_modules while index < member_modules.length return true if obj.is_a?(member_modules[index]) index += 1 end else members = types while index < members.length return true if members.fetch(index).valid?(obj) index += 1 end end false end |