Adding a nilable variable to a non-nilable array

118 Views Asked by At

I have a string array named current_todos and am trying to add a variable of type (String | Nil) named new_task by doing the following:

current_todos << new_task if typeof(new_task) == String

I get the error Error: no overload matches 'Array(String)#<<' with type (String | Nil).

How can I add a nilable string to current_todos after doing a type check?

Edit: here is the full code:

require "option_parser"

current_todos = [
    "Laundry",
    "Walk dog",
    "Sing in shower"
]

new_task = nil

OptionParser.parse do |parser|
    parser.banner = "Welcome to my todo app!"

    parser.on "-a TASK", "--add TASK", "Type a new task" do |task|
        new_task = task
    end
    
    parser.on "-h", "--help" do
        puts parser
        exit
    end
end

current_todos << new_task if typeof(new_task) == String

current_todos.each do |todo|
    puts todo
end
3

There are 3 best solutions below

2
Philipp Claßen On

If new_task is of type String|Nil, you can test if it is non-nil. Then the compiler will know that it is a string. That here should work:

current_todos << new_task if new_task

Another way that the compiler will understand, which is closer to your original code, is to use is_a?:

current_todos << new_task if new_task.is_a?(String)
1
borrimorri On

Looks like the reason something like current_todos << new_task if new_task.is_a?(String) doesn't work is because the new assignment of new_task happens within the .on function of the parser. Since the compiler doesn't know when/if this is called as it is inside a closure, it resorts to nil.

To force it to work I would need to use .not_nil!

0
Will Richardson On

typeof(var) gives the compile time type, not the type at runtime. For example:

def check_type(var : String?)
  puts typeof(var)
  puts var.class
  puts var.is_a? String
  puts var.is_a? Nil
  puts var.nil?
end

check_type(gets)

If you give input, it will print:

(String | Nil)
String
true
false
false

If you don't give input (gets returns nil) then it will print:

(String | Nil)
Nil
false
true
true