Q&A
How to check the data type of a variable in Ruby
Overview
Ruby is dynamically typed - variables don't declare types, and any variable can hold any object. Everything (including numbers and nil) is an object with a class. To find out what something is at runtime, you ask the object itself via methods like .class and .is_a?. Idiomatic Ruby often prefers duck typing (does it respond to the method I need?) over explicit type checks.
graph TD
A[Check a variable's type] --> B[.class → exact class]
A --> C[.is_a? / .kind_of? → class OR ancestor]
A --> D[.instance_of? → exact class only]
A --> E[.respond_to? → duck typing: can it do X?]
style C fill:#1e1b4b,color:#fff
.class - the object's class
42.class # Integer
3.14.class # Float
"hello".class # String
:sym.class # Symbol
[1, 2].class # Array
{ a: 1 }.class # Hash
nil.class # NilClass
true.class # TrueClass
(1..5).class # Range
.class returns the exact class of the object. You can compare it: x.class == String.
.is_a? / .kind_of? - includes ancestors
These return true if the object is an instance of the given class or any of its superclasses/modules:
42.is_a?(Integer) # true
42.is_a?(Numeric) # true - Integer < Numeric (inheritance)
42.is_a?(Comparable) # true - Integer includes the Comparable module
42.kind_of?(Float) # false
is_a? and kind_of? are aliases - identical behavior. This is usually what you want for type checks because it respects the class hierarchy.
.instance_of? - exact class only
42.instance_of?(Integer) # true
42.instance_of?(Numeric) # false - Numeric is an ancestor, not the exact class
Use instance_of? only when you need the precise class and want to exclude subclasses.
Comparison Table
For x = 42 (an Integer, whose ancestors include Numeric, Comparable, Object):
| Check | Result |
|---|---|
x.class |
Integer |
x.is_a?(Integer) |
true |
x.is_a?(Numeric) |
true (ancestor) |
x.instance_of?(Integer) |
true |
x.instance_of?(Numeric) |
false (not exact) |
Duck Typing - the idiomatic alternative
Ruby culture favors asking "can this object do what I need?" over "what class is it?":
if obj.respond_to?(:each)
obj.each { |item| ... } # works for Array, Hash, Range, custom iterables…
end
respond_to?(:method) checks whether the object has a given method. This is more flexible than rigid type checks and is often the preferred Ruby style.
Case/when with Types
Ruby's case uses ===, which for classes means is_a?:
case value
when Integer then "a number"
when String then "text"
when Array then "a list"
else "something else"
end
Why This Matters in Interviews
Ruby interviews use this to test understanding of dynamic typing and the object model. Key distinctions: .class (exact class), .is_a?/.kind_of? (class or ancestor - the usual choice), and .instance_of? (exact only). The mature, idiomatic point is that Ruby favors duck typing (respond_to?) over explicit type checking, and that case/when uses === (≈ is_a?) under the hood. Knowing everything is an object (even nil → NilClass) rounds it out.
Common Pitfalls
- Using
instance_of?when you meantis_a?, wrongly excluding subclasses. - Comparing
x.class == SomeClassinstead ofis_a?, missing inheritance. - Over-relying on type checks where duck typing (
respond_to?) would be more flexible/idiomatic. - Forgetting
nil,true,falseare objects (NilClass,TrueClass,FalseClass).
References
- Ruby
Object#is_a?/class: https://docs.ruby-lang.org/en/master/Object.html - Ruby duck typing overview: https://docs.ruby-lang.org/en/master/syntax.html