DEV Community

Yuta Goto
Yuta Goto

Posted on

hello gem steep

Ruby3.0から静的型チェックする機能が追加されるということで、軽く触ったので備忘録です。

SteepというGemを使いました。

GitHub logo soutaro / steep

Static type checker for Ruby

Steep - Gradual Typing for Ruby

Installation

Install via RubyGems.

$ gem install steep

Requirements

Steep requires Ruby 2.6 or later.

Usage

Steep does not infer types from Ruby programs, but requires declaring types and writing annotations You have to go on the following three steps.

0. steep init

Run steep init to generate a configuration file.

$ steep init       # Generates Steepfile

Edit the Steepfile:

target :app do
  check "lib"
  signature "sig"
  library "set", "pathname"
end
Enter fullscreen mode Exit fullscreen mode

1. Declare Types

Declare types in .rbs files in sig directory.

class Person
  @name: String
  @contacts: Array[Email | Phone]
  def initialize: (name: String) -> untyped
  def name: -> String
  def contacts: -> Array[Email | Phone]
  def guess_country: -> (String | nil)
end

class Email
  @address: String

  def initialize: (address: String) -> untyped
  def address: -> String
end

class Phone
  @country: String
  @number: String

  def initialize: (country: String, number: String) -> untyped

練習リポジトリ


結果

やっていること

lib/ ディレクトリにいつもどおりにクラスを定義します。

# lib/hello.rb
class Hello
  def initialize(name)
    @name = name
  end

  def say
    "hello, #{@name}"
  end
end
Enter fullscreen mode Exit fullscreen mode

sig/ ディレクトリに型の定義を書いていきます。拡張子は .rbi になります。

# sig/hello.rbi
class Hello < Object
  @name: String

  def initialize: (String) -> any
  def say: -> String
end
Enter fullscreen mode Exit fullscreen mode

メインで使ってみます。

# app.rb
require "./lib/hello"

hello1 = Hello.new('John')
puts hello1.say

hello2 = Hello.new(123)
puts hello2.say
Enter fullscreen mode Exit fullscreen mode

この app.rbhello2 に代入するときの Helloinitialize するときの引数の型が違っています。ただこのまま実行してもとくにエラーもなく実行することができます。
このあたりもチェックさせることができます。

$ bundle exec steep check --fallback-any-is-error app.rb
app.rb:6:19: ArgumentTypeMismatch: receiver=::Hello.class constructor, expected=::String, actual=::Integer (123)
Enter fullscreen mode Exit fullscreen mode

6行目のところで引数の型が違うことを指摘してくれたので、成功です。

所管

シンプルなクラス定義などではかなり簡単に使うことができて、とてもよさそうです。
RailsのモデルメソッドやServiceクラスなど部分的にもRailsプロジェクトに取り込めそうでちょっと型安全になるかもしれません。

Discussion (0)