LoginSignup
5
1

More than 1 year has passed since last update.

[Ruby3.0]型推論、型検査(Typeprof、Steep)を試してみる

Last updated at Posted at 2023-05-04

はじめに

今まで2系で使っていたプロジェクトを3系にバージョンアップするにあたって、型検査導入しようと思って調べました。

使用ライブラリ

おそらく型検査とか型推論とか調べると、TypeprofSteepが出てくるんですが、最初使い分けが分かりにくいのですが、以下資料のこの画像が全てかなと思います。

image.png
※「Ruby 3の型推論やってます」より引用

この、ruby-type-profiler = TypeProfですね。

つまり、TypeProfは実コードからrbsファイル(型が記述されたファイル)を生成し、Steepはその型定義から実コードを型検査するという役割です。

もう少し細かく解説するなら、

  • TypeProfのメイン機能は型推論なので、例えばVSCodeのプラグイン入れればコード補完や型の間違いを指摘してくれる(ただ、型推論の精度は完璧ではないので適宜自分で型ファイルを修正する)
  • rbsファイルを1から自分で作ればTypeProf使わなくてもSteepで型検査できる。こちらもプラグインを入れれば型検査の結果をIDE上で表示してくれます。

TypeProf

以下の記事を参考にTypeProf導入します。

Ruby3.1 静的解析の導入で開発体験を向上させる (RBS, TypeProf)|Offers Tech Blog

色々頑張ったんですが、私の環境だとVSCodeのプラグインは動いてくれませんでしたが、typeprofコマンドで型ファイルを生成するところまではできました。

Steep

以下の記事を参考にTypeProf導入します。

Steepを使ってRubyの型検査に入門する

こちらはVSCodeのプラグインが無事動作してくれたので、ちょっと確認してみます。
上記の記事のサンプルコードを使用させて頂きます。上記記事では自分で書いたrbsファイルを使用していました、今回はtypeprof導入済みのため、こちらで生成したrbsファイルを利用してみます。

class Person
  attr_reader :name
  attr_reader :gender

  def initialize(name:, gender:)
    @name = name
    @gender = gender
  end
end

こちらのクラスが記述されているファイルをtypeprofで読み込むと以下のようなrbsファイルが得られます。

# TypeProf 0.21.7

# Classes
class Person
  attr_reader name: untyped
  attr_reader gender: untyped
  def initialize: (name: untyped, gender: untyped) -> void
end

まあ、nameもgenderも何が入るかは全くわからないので、当たり前と言えば当たり前のようにuntypedが入りますね。
一つメソッドを追加して、改めてrbsファイルを生成します。

class Person
  attr_reader :name
  attr_reader :gender

  def initialize(name:, gender:)
    @name = name
    @gender = gender
  end

  def hello
    "hello, #{name}. You are #{gender}."
  end
end
# TypeProf 0.21.7

# Classes
class Person
  attr_reader name: untyped
  attr_reader gender: untyped
  def initialize: (name: untyped, gender: untyped) -> void
  def hello: -> String
end

helloの返り値がStringということは推定されていますが、nameもgenderもIntegerが入ってきても特に問題なく処理されるのでuntypedになっていますね。

この状態で、Personをただnewすると、引数が足らないというエラーがちゃんと出てくれますね。

image.png

steep checkコマンドをコンソールで叩いても同様のエラーが出ます。

image.png

あとは、気になることとしてrbsファイルに書いてあるメソッドが実装されていない場合どうなるか、つまりinterface的に使えるのかちょっと確認してみます。

# TypeProf 0.21.7

# Classes
class Person
  attr_reader name: untyped
  attr_reader gender: untyped
  def initialize: (name: untyped, gender: untyped) -> void
  def hello: -> String
  def male?: -> bool
end

steep checkの結果は、以下です。
image.png

まあ当たり前といえば当たり前ですね。依存関係をチェックしているわけではなく、間違った型の使われていないかチェックしているのでinterface的な使い方は難しいっぽいです。

これ入れてくれると結構良さげかなと思いました。動的言語にわざわざ型チェック入れてるんだからついでにinterface入れてくれても的な。

まとめ

Rubyの型検査に関してはまだ発展途上な感じがしていて、もうちょっと使いやすくなれば導入可能かなと思いました。
現状、1から導入するのであれば、そこまでハードル高くないですが、既存プロジェクトに適用するとなるとかなり大変だなぁと。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1