TypeError

Non conversionem animae viventis

Ruby's TypeError class

TypeError is raised when encountering an object that is not of the expected type.

[1, 2, 3].first("two")

raises the exception:

TypeError: no implicit conversion of String into Integer

Superclass

StandardError

Enemies

Honeybadger

» This Is Not the Type You're Looking For

In the example above, the user has passed "two", a String, as an argument to the Array#first method, which expects a type Integer. When this happens, Ruby raises TypeError to alert the user that it can't use the type of object that was passed in to produce a meaningful result.

Another example of TypeError in Ruby is when using many of the built-in conversion functions to convert one type to another. When the object passed to each function cannot be automatically converted to the correct type, Ruby raises TypeError:

Complex(nil)    # => TypeError
Hash([1, 2, 3]) # => TypeError
Integer(nil)    # => TypeError
Rational(nil)   # => TypeError

» How To Use TypeError in Your Ruby Code

Let's take a look at a hypothetical method which requires a special kind of type in order to return a valid result:

CREATURES = ['NoMethodError', 'TypeError', 'ArgumentError', 'RuntimeError']

def print_random(number)
  number.times do
    puts CREATURES.sample
  end
end

The print_random method receives one argument, number, which tells the method how many times to print a random creature. This works beautifully when called with an Integer:

irb(main):012:0> print_random(3)
TypeError
ArgumentError
TypeError
=> 3

Unfortunately, we get a much more confusing result when calling the method with an unexpected argument, nil:

irb(main):015:0> print_random(nil)
NoMethodError: undefined method `times' for nil:NilClass

A solution to this problem could be to explicitly convert the object to an Integer before calling #times on it:

def print_random(number)
  number.to_i.times do
    puts CREATURES.sample
  end
end

Now, when we call print_random with nil, we at least don't get an error:

irb(main):034:0> print_random(nil)
=> 0

That's not a very meaningful result either, though. nil doesn't give print_random enough information to do what the user asked—print a random list of creatures. It would be much better to raise an exception so that the user can correct their mistake. TypeError to the rescue (no pun intended ;))!

def print_random(number)
  raise TypeError, "expected an Integer, got #{number.class.name}" unless number.is_a?(Integer)
  number.times do
    puts CREATURES.sample
  end
end

Now, calling our method with nil produces a helpful error which tells us exactly what we did wrong:

irb(main):041:0> print_random(nil)
TypeError: expected an Integer, got NilClass

While this method is improved with an explicit type check, we can make it even more robust while providing the same feedback by using one of the type conversion functions that we mentioned earlier. Let's take a look at an alternate implementation:

def print_random(number)
  Integer(number).times do
    puts CREATURES.sample
  end
end

Now our method can be called with any object that supports implicit conversion to an Integer, and it still raises TypeError when it can't do the conversion:

irb(main):012:0> print_random(2)
TypeError
ArgumentError
=> 2

irb(main):012:0> print_random("1")
RuntimeError
=> 1

irb(main):041:0> print_random(nil)
TypeError: can't convert nil into Integer