类型检查后仍报错:如何将可空字符串加入非可空数组?
问题描述
我有一个名为current_todos的字符串数组,尝试将类型为(String | Nil)的变量new_task通过以下代码添加进去:
current_todos << new_task if typeof(new_task) == String
但收到错误提示:Error: no overload matches 'Array(String)#<<' with type (String | Nil)。
请问在完成类型检查后,如何将这个可空字符串添加至current_todos数组中?
补充完整代码:
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
解决方案
在Crystal语言中,typeof是编译时操作符,仅用于获取类型信息,无法在运行时帮你完成类型窄化,所以编译器仍会认为new_task是String | Nil类型,导致报错。你需要用运行时类型检查让编译器确认变量类型,以下是两种可行方案:
方案一:用is_a?做类型判断
直接用is_a? String替代typeof判断,编译器会自动窄化变量类型:
current_todos << new_task if new_task.is_a? String
方案二:用nil?反向判断
因为new_task只有String和Nil两种可能,判断它不为nil后,编译器能推断出它是String类型:
current_todos << new_task unless new_task.nil?
额外优化
你还可以直接在OptionParser的on块内完成添加操作,省去额外的new_task变量,代码更简洁:
require "option_parser" current_todos = [ "Laundry", "Walk dog", "Sing in shower" ] OptionParser.parse do |parser| parser.banner = "Welcome to my todo app!" parser.on "-a TASK", "--add TASK", "Type a new task" do |task| current_todos << task # 此处task已确定为String类型,无需额外判断 end parser.on "-h", "--help" do puts parser exit end end current_todos.each do |todo| puts todo end
内容的提问来源于stack exchange,提问作者borrimorri
相关产品推荐
相关产品推荐

