Module: EasyTalk::TypeIntrospection
- Defined in:
- lib/easy_talk/type_introspection.rb
Overview
Centralized module for robust type introspection.
This module provides predicate methods for detecting types without relying on brittle string-based checks. It uses Sorbet's type system properly and handles edge cases gracefully.
Constant Summary collapse
- PRIMITIVE_TO_JSON_SCHEMA =
Mapping of Ruby classes to JSON Schema types
{ String => 'string', Integer => 'integer', Float => 'number', BigDecimal => 'number', TrueClass => 'boolean', FalseClass => 'boolean', NilClass => 'null' }.freeze
Class Method Summary collapse
-
.boolean_type?(type) ⇒ Boolean
Check if type represents a boolean (T::Boolean or TrueClass/FalseClass).
-
.extract_inner_type(type) ⇒ Object
Extract inner type from nilable or complex types.
-
.get_type_class(type) ⇒ Class, ...
Get the Ruby class for a type, handling Sorbet types.
-
.json_schema_type(type) ⇒ String
Get JSON Schema type string for a Ruby type.
-
.nilable_type?(type) ⇒ Boolean
Check if type is nilable (T.nilable(...)).
-
.primitive_type?(type) ⇒ Boolean
Check if type is a primitive Ruby type.
-
.typed_array?(type) ⇒ Boolean
Check if type is a typed array (T::Array[...]).
Class Method Details
.boolean_type?(type) ⇒ Boolean
Check if type represents a boolean (T::Boolean or TrueClass/FalseClass).
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/easy_talk/type_introspection.rb', line 44 def boolean_type?(type) return false if type.nil? return true if [TrueClass, FalseClass].include?(type) return true if type.respond_to?(:raw_type) && [TrueClass, FalseClass].include?(type.raw_type) # Check for T::Boolean which is a TypeAlias with name 'T::Boolean' return true if type.respond_to?(:name) && type.name == 'T::Boolean' # Check for union types containing TrueClass and FalseClass if type.respond_to?(:types) type_classes = type.types.map { |t| t.respond_to?(:raw_type) ? t.raw_type : t } return type_classes.sort_by(&:name) == [FalseClass, TrueClass].sort_by(&:name) end false end |
.extract_inner_type(type) ⇒ Object
Extract inner type from nilable or complex types.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/easy_talk/type_introspection.rb', line 158 def extract_inner_type(type) return type if type.nil? if type.respond_to?(:unwrap_nilable) unwrapped = type.unwrap_nilable return unwrapped.respond_to?(:raw_type) ? unwrapped.raw_type : unwrapped end if type.respond_to?(:types) non_nil = type.types.find do |t| raw = t.respond_to?(:raw_type) ? t.raw_type : t raw != NilClass end return non_nil.respond_to?(:raw_type) ? non_nil.raw_type : non_nil if non_nil end type end |
.get_type_class(type) ⇒ Class, ...
Get the Ruby class for a type, handling Sorbet types.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/easy_talk/type_introspection.rb', line 136 def get_type_class(type) return nil if type.nil? return type if type.is_a?(Class) return type.raw_type if type.respond_to?(:raw_type) return Array if typed_array?(type) return [TrueClass, FalseClass] if boolean_type?(type) if nilable_type?(type) inner = extract_inner_type(type) return get_type_class(inner) if inner && inner != type end nil end |
.json_schema_type(type) ⇒ String
Get JSON Schema type string for a Ruby type.
114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/easy_talk/type_introspection.rb', line 114 def json_schema_type(type) return 'object' if type.nil? return 'boolean' if boolean_type?(type) resolved_class = if type.is_a?(Class) type elsif type.respond_to?(:raw_type) type.raw_type end PRIMITIVE_TO_JSON_SCHEMA[resolved_class] || resolved_class&.name&.downcase || 'object' end |
.nilable_type?(type) ⇒ Boolean
Check if type is nilable (T.nilable(...)).
83 84 85 86 87 |
# File 'lib/easy_talk/type_introspection.rb', line 83 def nilable_type?(type) return false if type.nil? type.respond_to?(:nilable?) && type.nilable? end |
.primitive_type?(type) ⇒ Boolean
Check if type is a primitive Ruby type.
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/easy_talk/type_introspection.rb', line 93 def primitive_type?(type) return false if type.nil? resolved = if type.is_a?(Class) type elsif type.respond_to?(:raw_type) type.raw_type end PRIMITIVE_TO_JSON_SCHEMA.key?(resolved) end |
.typed_array?(type) ⇒ Boolean
Check if type is a typed array (T::Array[...]).
69 70 71 72 73 |
# File 'lib/easy_talk/type_introspection.rb', line 69 def typed_array?(type) return false if type.nil? type.is_a?(T::Types::TypedArray) end |