rubygeokitsorbet

Why does Sorbet think that a method I provided an explicit signature for in an RBI file doesn't exist?


One of my classes depends on the gem Geokit, which doesn't provide an RBI file of its own nor is it included in the sorbet-typed repo. I hand-wrote a couple RBI files for it myself, including signatures for the methods that I use in my own code.

When I attempt to change the class that depends on Geokit to typed: true, it complains that the methods I'm using don't exist.

The class typechecks fine under typed: false.

geokit.rbi

# typed: strong

module Geokit
end

bounds.rbi

# typed: strong

class Geokit::Bounds
    sig do
        params(
            thing: T.any(Geokit::Bounds, T::Array[T.any(T::Array[Numeric], Numeric, String)], String, Geokit::LatLng),
            other: T.nilable(T.any(T::Array[Numeric], String, Geokit::LatLng))
        ).returns(Geokit::Bounds)
    end
    def normalize(thing, other = nil); end
end

lib/platform/x.rb

class X
  BOUNDS = Geokit::Bounds.normalize([[0.8852118e2, -0.751305e1], [0.689324e2, -0.386637e1]])
end

The error I get is as follows:

lib/platform/x.rb:2: Method normalize does not exist on T.class_of(Geokit::Bounds) https://srb.help/7003
     2 |  BOUNDS = Geokit::Bounds.normalize([[0.8852118e2, -0.751305e1], [0.689324e2, -0.386637e1]])
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  Autocorrect: Use `-a` to autocorrect
    lib/platform/x.rb:2: Replace with initialize
     2 |  BOUNDS = Geokit::Bounds.normalize([[0.8852118e2, -0.751305e1], [0.689324e2, -0.386637e1]])

Solution

  • You are missing self. in the RBI definition of that method. Sorbet thinks that normalize is an instance method on Bounds.

    # typed: strong
    
    class Geokit::Bounds
        sig do
            params(
                thing: T.any(Geokit::Bounds, T::Array[T.any(T::Array[Numeric], Numeric, String)], String, Geokit::LatLng),
                other: T.nilable(T.any(T::Array[Numeric], String, Geokit::LatLng))
            ).returns(Geokit::Bounds)
        end
        def self.normalize(thing, other = nil); end
    end