You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类型检查后仍报错:如何将可空字符串加入非可空数组?

问题描述

我有一个名为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 07:45:30