T‑Ruby:在 Ruby 中添加静态类型而不产生运行时开销

发布: (2026年2月25日 GMT+8 05:50)
6 分钟阅读
原文: Dev.to

Source: Dev.to

T‑Ruby:在 Ruby 中添加静态类型而不产生运行时开销的封面图像

介绍

静态类型是一种强大的工具,为各种规模的代码库带来巨大的价值。从小脚本到庞大的单体应用,这些好处不容忽视:你可以获得始终保持最新的实时文档、提升的可读性,以及显著提升代码可靠性的可靠安全网。

不同的动态语言走了各自的道路来解决类型难题。Python 引入了原生但可选的类型提示,而 JavaScript 生态系统则完全转向了独立语言 TypeScript。在 Ruby 社区,我们看到了 RBSSorbet 两种不同的实现,最近由于 RBS inline 的引入以及 Sorbet 对其的支持,这两者开始趋于融合。

然而,当前的 Ruby 方案并非毫无摩擦。对许多开发者而言,类型仍然更像是个人偏好,而非核心需求。由于类型检查常被视为“额外”的东西,静态检查很容易被忽视或完全遗忘。

什么是 T‑Ruby?

一个正在获得关注的突破性实验是 T‑Ruby。与标准的运行时类型检查系统不同,T‑Ruby 将带类型的代码编译为纯粹、未装饰的 Ruby,且没有任何运行时开销。简而言之,T‑Ruby 本质上是 Ruby 语言的 TypeScript:你编写受 RBS 启发的代码,最终会被编译成普通的标准 Ruby。

虽然有些人可能会建议使用 Crystal,但两者在理念上有根本区别。Crystal 是一种独立的、类似 Ruby 的语言,拥有自己的生态系统。而 T‑Ruby 则是一个额外的层,旨在保持与我们已经熟悉的 Ruby 紧密相连。就像 TypeScript 最终会输出纯 JavaScript,T‑Ruby 确保你的最终产物仍然是纯 Ruby。

示例:带类型的 HTTP 客户端

下面是一个简单的 HTTP 客户端,它从 GitHub 获取最新的 Ruby 发布标签。使用 T‑Ruby,类型直接嵌入到类结构中。

require "httparty"
require "json"
require "time"

class RubyVersion
  API_URL = "https://api.github.com/repos/ruby/ruby/releases/latest"

  class Response
    attr_reader :code: Integer
    attr_reader :json: Hash

    def initialize(code: Integer, json: Hash): nil
      @code = code
      @json = json
    end

    def success?: Boolean
      (200..299).include?(@code)
    end
  end

  def fetch_response: Response
    http = HTTParty.get(API_URL, headers: { 'User-Agent' => 'static-typing-demo' })
    Response.new(http.code.to_i, JSON.parse(http.body))
  end

  def self.fetch(printer: Proc<[String, String, Time], nil]): nil
    resp = new.fetch_response
    raise "HTTP #{resp.code}" unless (200..299).include?(resp.code)
    data = resp.json
    published = Time.parse((data['published_at'] || Time.now.utc.iso8601).to_s)
    printer.call((data['tag_name'] || data['name']).to_s, data['html_url'], published)
  end
end

通过添加这些类型,我们可以严格定义 Proc 的结构,并确保系统中传递的数据是有效的。在标准 Ruby 中,我们通常依赖文档或手动的守卫子句来实现这种确定性。

设置 T‑Ruby

  1. 安装 gem:

    gem install t-ruby
  2. 初始化配置文件:

    trc --init

生成的配置允许您指定 *.trb 文件的源文件夹、编译后 Ruby 的输出位置,以及诸如自动运行 RSpec 或 Minitest 的编译后命令。

Rails Integration (Experimental)

Rails 依赖特定的文件夹结构,因此最简洁的方法是将整个 app 文件夹存放在你的 T‑Ruby 源代码目录中。那些不包含 T‑Ruby 语法的文件会直接原样复制到目标文件夹。这与现代 JavaScript 框架(如 Next.js)中常见的 /src / /dist 工作流相呼应。

当前状态与展望

T‑Ruby 仍处于 技术预览 阶段。网站和文档看起来很精致,但实现可能不太稳定——官方示例在安装后可能会立即失败。

尽管有这些粗糙之处,但其潜力不可否认。在一个小型 Rails 应用中使用 T‑Ruby,省去了单独维护 RBS 文件的需求。将类型与业务逻辑一起编写感觉很自然,并且在编译时知道代码是“类型正确”的,这带来了独特的安心感。这是 Ruby 生态系统的一大进步,即使它尚未完全准备好用于生产环境。

最初发布于我的博客.

0 浏览
Back to Blog

相关文章

阅读更多 »

小事,大影响

!尾随逗号示例https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s...

Steel Bank Common Lisp

关于 Steel Bank Common Lisp(SBCL),它是一款高性能的 Common Lisp 编译器。它是开源/自由软件,采用宽松的许可证。除此之外,...

简化 Rails 中的时间戳切换

概述:我经常使用时间戳(例如 completed_at)作为布尔标志。它比真正的布尔值提供更多的元数据,但在 UI 上你通常希望…

停止在 Rails 中错误使用 .any?

介绍:传递给 .any? 的单个块可能会在不发出警告或错误的情况下,悄悄将成千上万条记录加载到内存中——仅仅是产生不必要的对象。大多数 Rails 开发者……