class T::Types::FixedArray
in the list.
Takes a list of types. Validates each item in an array using the type in the same position
def describe_obj(obj)
"Expected [String, Symbol], got Array".
instead of
"Expected [String, Symbol], got [String, String]"
This gives us better errors, e.g.:
def describe_obj(obj) if obj.is_a?(Array) if obj.length == @types.length item_classes = obj.map(&:class).join(', ') "type [#{item_classes}]" else "array of size #{obj.length}" end else super end end
def initialize(types)
def initialize(types) @types = types.map {|type| T::Utils.coerce(type)} end
def name
def name "[#{@types.join(', ')}]" end
def recursively_valid?(obj)
def recursively_valid?(obj) if obj.is_a?(Array) && obj.length == @types.length i = 0 while i < @types.length if !@types[i].recursively_valid?(obj[i]) return false end i += 1 end true else false end end
def subtype_of_single?(other)
def subtype_of_single?(other) ther ixedArray operly speaking, covariance here is unsound since arrays n be mutated, but sorbet implements covariant tuples for se of adoption. es.size == other.types.size && @types.zip(other.types).all? do |t1, t2| .subtype_of?(t2) e
def valid?(obj)
def valid?(obj) if obj.is_a?(Array) && obj.length == @types.length i = 0 while i < @types.length if !@types[i].valid?(obj[i]) return false end i += 1 end true else false end end