Checking Your Types
An overview of Ruby's type system
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Checking Your Types
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Checking Your Types
• refresh ourselves on type systems
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Checking Your Types
• refresh ourselves on type systems
• types in Ruby
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Checking Your Types
• refresh ourselves on type systems
• types in Ruby
• What's new in Ruby 3
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Checking Your Types
• refresh ourselves on type systems
• types in Ruby
• What's new in Ruby 3
• Typecheckers
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Checking Your Types
• refresh ourselves on type systems
• types in Ruby
• What's new in Ruby 3
• Typecheckers
• Examples!
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
What are types?
Javascript
>> num = 2
2
>> console.log(typeof num);
number
C
char string[] = "C strings are arrays of characters";
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Static vs. Dynamic
When do we know what types we're working with?
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Static
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Static
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Static
• Knows types beforehand.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Static
• Knows types beforehand.
• As a party host, knows the number of guests to cater for.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Dynamic
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Dynamic
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Dynamic
• Knows types when they show up.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Dynamic
• Knows types when they show up.
• Probably easier to crash their party /
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Ambiguous territory ahead
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Strong vs. Weak Types
"...whenever an object is passed from a calling function to a called
function, its type must be compatible with the type declared in the
called function."
- Liskov & S. Zilles, 19741
1 
Liskov, B; Zilles, S (1974). "Programming with abstract data types". ACM SIGPLAN Notices. 9 (4): 50–59.
CiteSeerX 10.1.1.136.3043. doi:10.1145/942572.807045.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Strongly typed language
>> num = 2
2
>> num[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable
>> num + "hello"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Weakly typed language
>> num = 2
2
// It will always try:
>> num[0]
undefined
// But sometimes this means strange things can happen:
>> num + "hello"
"2hello"
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Where would Ruby land?
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Dynamic, strong typing
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Conversion between types in Ruby
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Explicit Conversion
birthday = Time.new(1993, 02, 24)
birthday.to_s
=> "1993-02-24 00:00:00 -0500"
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Implicit Conversion
require "bigdecimal"
BigDecimal("101.1111").to_int
=> 101
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Numeric conversion
2 + 26.3
=> 28.3
# The above works because the `coerce` method is called before adding:
2.coerce(26.3)
=> [26.3, 2.0]
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
!
Why add types to Ruby? Isn't this making
the language less expressive?
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
!
Why add types to Ruby? Isn't this making the
language less expressive?
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
!
Why add types to Ruby? Isn't this making the
language less expressive?
• Improved tooling means less mental overhead
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
!
Why add types to Ruby? Isn't this making the
language less expressive?
• Improved tooling means less mental overhead
• Ruby's strong type system means we're already having to
concern ourselves with passing around valid types
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
✨
Ruby 3
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
✨
Ruby 3
• RBS, a language for describing the types of a Ruby program.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
✨
Ruby 3
• RBS, a language for describing the types of a Ruby program.
• Typeprof
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
https://mame.github.io/typeprof-playground/
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Gradual Type Checking
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
NoMethodErrors
# Here we try to call an instance method on the CreditCard class
class CreditCard
def number
end
end
CreditCard.number
NoMethodError (undefined method `number' for CreditCard:Class)
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Type Signature Support (RBS)
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Type Signature Support (RBS)
• Separate file of type declarations, similar to .d.ts in Typescript
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Type Signature Support (RBS)
• Separate file of type declarations, similar to .d.ts in Typescript
• Standalone language, separate from Ruby but describes Ruby
types
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
!
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Type Signature Support (RBS)
# steep/sample/sig/conference.rbs
class Conference
attr_reader title: String
attr_reader year: Integer
def initialize: (title: String, year: Integer) -> void
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Typecheckers
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Typecheckers
• Sorbet
!
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Typecheckers
• Sorbet
!
• Steep
"
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class CreditCard
...
end
class DebitCard
...
end
class User
def payment_method
# (Returns CreditCard or DebitCard)
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class CreditCard
...
end
class DebitCard
...
end
class User
def payment_method
# (Returns CreditCard or DebitCard or Instalments)
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
! ! !
ArgumentError: "unknown payment type"
! ! !
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when CreditCard
render snippet: 'credit_card'
when DebitCard
render snippet: 'debit_card'
else
raise 'unknown payment type'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
# sig/user.rbs
class User
def payment_method: () -> ???
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethod
def charge(_amount)
raise 'unimplemented'
end
end
interface _PaymentMethod
def charge: (Money amount) -> void
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethod
def charge(_amount)
raise 'unimplemented'
end
end
interface _PaymentMethod
def charge: (Money amount) -> void
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
interface _PaymentMethod
def charge: (Money amount) -> void
end
class DebitCard
include _PaymentMethod # Note: not actually adding any behaviour!
def charge
...
end
end
class CreditCard
include _PaymentMethod # Note: not actually adding any behaviour!
def charge
...
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
# sig/user.rbs
class User
def payment_method: () -> _PaymentMethod
end
# sig/payment_method_presenter.rbs
class PaymentMethodPresenter
attr_reader payment_method: _PaymentMethod
def render: () -> String
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when creditcard
render snippet: 'credit_card'
when debitcard
render snippet: 'debit_card'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
Error: PaymentMethodPresenter#render claims it returns String, but
actually returns String | nil
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when CreditCard
render snippet: 'credit_card'
when DebitCard
render snippet: 'debit_card'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when CreditCard
render snippet: 'credit_card'
when DebitCard
render snippet: 'debit_card'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
!
We can use a union type definition to specify permitted types.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
# sig/user.rbs
type payment_method = DebitCard | CreditCard
class User
def payment_method: () -> payment_method
end
# sig/payment_method_presenter.rbs
class PaymentMethodPresenter
attr_reader payment_method: payment_method
def render: () -> String
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
# sig/user.rbs
type payment_method = DebitCard | CreditCard | Instalments
class User
def payment_method: () -> payment_method
end
# sig/payment_method_presenter.rbs
class PaymentMethodPresenter
attr_reader payment_method: payment_method
def render: () -> String
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when CreditCard
render snippet: 'credit_card'
when DebitCard
render snippet: 'debit_card'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when CreditCard
render snippet: 'credit_card'
when DebitCard
render snippet: 'debit_card'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when CreditCard
render snippet: 'credit_card'
when DebitCard
render snippet: 'debit_card'
when Instalments
render snippet: 'instalments'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
class PaymentMethodPresenter
def render
case payment_method
when CreditCard
render snippet: 'credit_card'
when DebitCard
render snippet: 'debit_card'
when Instalments
render snippet: 'instalments'
end
end
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Payments Example
# sig/user.rbs
type payment_method = DebitCard | CreditCard | Instalments
class User
def payment_method: () -> payment_method
end
# sig/payment_method_presenter.rbs
class PaymentMethodPresenter
attr_reader payment_method: payment_method
def render: () -> String
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
What about reducing NoMethodError?
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Addressable Example
Addressable::URI.parse("https://example.com/foo.css?v=123123").query_values
=> { "v" => "123123" }
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Addressable Example
version = Addressable::URI.parse(url).query_values['v']
unless version
render :bad_request
return
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Addressable Example
Addressable::URI.parse("https://example.com").query_values
=> nil
Addressable::URI.parse("https://example.com?").query_values
=> {}
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Addressable Example
class Baddressable
def initialize(uri)
@uri = uri
end
def query_values
Hash[*URI.parse(@uri).query.split("=")]
end
end
Baddressable.new("https://example.com").query_values['v']
baddressable.rbs:
class Baddressable
def initialize: (String?) -> void
def query_values: -> Hash[String, String]?
end
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Addressable Example
[error] Type `(::Hash[::String, ::String] | nil)` does not have method `[]`
│ Diagnostic ID: Ruby::NoMethod
│
└ Baddressable.new("https://example.com").query_values['v']
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Takeaways
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Takeaways
• Types were always there; now we're able to work with them
more intentionally in Ruby.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Takeaways
• Types were always there; now we're able to work with them
more intentionally in Ruby.
• Using these type checking tools can help us ensure errors really
only happen once by making our code a little smarter.
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Takeaways
• Types were always there; now we're able to work with them
more intentionally in Ruby.
• Using these type checking tools can help us ensure errors really
only happen once by making our code a little smarter.
• It's going to take adoption and use by the community for this
feature to be as successful as possible!
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Thank you!
Sam Doiron @conlectus
Fleur de Ruby meetup @fleur_de_ruby
Grusp for hosting this event, & you for attending!
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
Go forth & build with types!
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/
@thecodewitch, slides available at thecodewitch.codes/checking-your-types/

Checking Your Types: An overview of Ruby's type system

  • 1.
    Checking Your Types Anoverview of Ruby's type system @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 2.
    Checking Your Types @thecodewitch,slides available at thecodewitch.codes/checking-your-types/
  • 3.
    Checking Your Types •refresh ourselves on type systems @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 4.
    Checking Your Types •refresh ourselves on type systems • types in Ruby @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 5.
    Checking Your Types •refresh ourselves on type systems • types in Ruby • What's new in Ruby 3 @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 6.
    Checking Your Types •refresh ourselves on type systems • types in Ruby • What's new in Ruby 3 • Typecheckers @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 7.
    Checking Your Types •refresh ourselves on type systems • types in Ruby • What's new in Ruby 3 • Typecheckers • Examples! @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 8.
    What are types? Javascript >>num = 2 2 >> console.log(typeof num); number C char string[] = "C strings are arrays of characters"; @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 9.
    Static vs. Dynamic Whendo we know what types we're working with? @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 10.
    Static @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 11.
    Static @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 12.
    Static • Knows typesbeforehand. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 13.
    Static • Knows typesbeforehand. • As a party host, knows the number of guests to cater for. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 14.
    Dynamic @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 15.
    Dynamic @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 16.
    Dynamic • Knows typeswhen they show up. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 17.
    Dynamic • Knows typeswhen they show up. • Probably easier to crash their party / @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 18.
    Ambiguous territory ahead @thecodewitch,slides available at thecodewitch.codes/checking-your-types/
  • 19.
    Strong vs. WeakTypes "...whenever an object is passed from a calling function to a called function, its type must be compatible with the type declared in the called function." - Liskov & S. Zilles, 19741 1  Liskov, B; Zilles, S (1974). "Programming with abstract data types". ACM SIGPLAN Notices. 9 (4): 50–59. CiteSeerX 10.1.1.136.3043. doi:10.1145/942572.807045. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 20.
    Strongly typed language >>num = 2 2 >> num[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not subscriptable >> num + "hello" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate str (not "int") to str @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 21.
    Weakly typed language >>num = 2 2 // It will always try: >> num[0] undefined // But sometimes this means strange things can happen: >> num + "hello" "2hello" @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 22.
    @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 23.
    Where would Rubyland? @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 24.
    @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 25.
    Dynamic, strong typing @thecodewitch,slides available at thecodewitch.codes/checking-your-types/
  • 26.
    Conversion between typesin Ruby @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 27.
    Explicit Conversion birthday =Time.new(1993, 02, 24) birthday.to_s => "1993-02-24 00:00:00 -0500" @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 28.
    Implicit Conversion require "bigdecimal" BigDecimal("101.1111").to_int =>101 @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 29.
    Numeric conversion 2 +26.3 => 28.3 # The above works because the `coerce` method is called before adding: 2.coerce(26.3) => [26.3, 2.0] @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 30.
    ! Why add typesto Ruby? Isn't this making the language less expressive? @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 31.
    ! Why add typesto Ruby? Isn't this making the language less expressive? @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 32.
    ! Why add typesto Ruby? Isn't this making the language less expressive? • Improved tooling means less mental overhead @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 33.
    ! Why add typesto Ruby? Isn't this making the language less expressive? • Improved tooling means less mental overhead • Ruby's strong type system means we're already having to concern ourselves with passing around valid types @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 34.
    ✨ Ruby 3 @thecodewitch, slidesavailable at thecodewitch.codes/checking-your-types/
  • 35.
    ✨ Ruby 3 • RBS,a language for describing the types of a Ruby program. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 36.
    ✨ Ruby 3 • RBS,a language for describing the types of a Ruby program. • Typeprof @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 37.
  • 38.
    Gradual Type Checking @thecodewitch,slides available at thecodewitch.codes/checking-your-types/
  • 39.
    NoMethodErrors # Here wetry to call an instance method on the CreditCard class class CreditCard def number end end CreditCard.number NoMethodError (undefined method `number' for CreditCard:Class) @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 40.
    Type Signature Support(RBS) @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 41.
    Type Signature Support(RBS) • Separate file of type declarations, similar to .d.ts in Typescript @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 42.
    Type Signature Support(RBS) • Separate file of type declarations, similar to .d.ts in Typescript • Standalone language, separate from Ruby but describes Ruby types @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 43.
    ! @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 44.
    Type Signature Support(RBS) # steep/sample/sig/conference.rbs class Conference attr_reader title: String attr_reader year: Integer def initialize: (title: String, year: Integer) -> void end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 45.
    Typecheckers @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 46.
    Typecheckers • Sorbet ! @thecodewitch, slidesavailable at thecodewitch.codes/checking-your-types/
  • 47.
    Typecheckers • Sorbet ! • Steep " @thecodewitch,slides available at thecodewitch.codes/checking-your-types/
  • 48.
    Payments Example class CreditCard ... end classDebitCard ... end class User def payment_method # (Returns CreditCard or DebitCard) end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 49.
    Payments Example class CreditCard ... end classDebitCard ... end class User def payment_method # (Returns CreditCard or DebitCard or Instalments) end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 50.
    Payments Example @thecodewitch, slidesavailable at thecodewitch.codes/checking-your-types/
  • 51.
    Payments Example ! !! ArgumentError: "unknown payment type" ! ! ! @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 52.
    Payments Example class PaymentMethodPresenter defrender case payment_method when CreditCard render snippet: 'credit_card' when DebitCard render snippet: 'debit_card' else raise 'unknown payment type' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 53.
    Payments Example # sig/user.rbs classUser def payment_method: () -> ??? end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 54.
    Payments Example class PaymentMethod defcharge(_amount) raise 'unimplemented' end end interface _PaymentMethod def charge: (Money amount) -> void end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 55.
    Payments Example class PaymentMethod defcharge(_amount) raise 'unimplemented' end end interface _PaymentMethod def charge: (Money amount) -> void end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 56.
    Payments Example interface _PaymentMethod defcharge: (Money amount) -> void end class DebitCard include _PaymentMethod # Note: not actually adding any behaviour! def charge ... end end class CreditCard include _PaymentMethod # Note: not actually adding any behaviour! def charge ... end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 57.
    Payments Example # sig/user.rbs classUser def payment_method: () -> _PaymentMethod end # sig/payment_method_presenter.rbs class PaymentMethodPresenter attr_reader payment_method: _PaymentMethod def render: () -> String end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 58.
    Payments Example class PaymentMethodPresenter defrender case payment_method when creditcard render snippet: 'credit_card' when debitcard render snippet: 'debit_card' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 59.
    Payments Example Error: PaymentMethodPresenter#renderclaims it returns String, but actually returns String | nil @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 60.
    Payments Example class PaymentMethodPresenter defrender case payment_method when CreditCard render snippet: 'credit_card' when DebitCard render snippet: 'debit_card' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 61.
    Payments Example class PaymentMethodPresenter defrender case payment_method when CreditCard render snippet: 'credit_card' when DebitCard render snippet: 'debit_card' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 62.
    Payments Example ! We canuse a union type definition to specify permitted types. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 63.
    Payments Example # sig/user.rbs typepayment_method = DebitCard | CreditCard class User def payment_method: () -> payment_method end # sig/payment_method_presenter.rbs class PaymentMethodPresenter attr_reader payment_method: payment_method def render: () -> String end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 64.
    Payments Example # sig/user.rbs typepayment_method = DebitCard | CreditCard | Instalments class User def payment_method: () -> payment_method end # sig/payment_method_presenter.rbs class PaymentMethodPresenter attr_reader payment_method: payment_method def render: () -> String end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 65.
    Payments Example class PaymentMethodPresenter defrender case payment_method when CreditCard render snippet: 'credit_card' when DebitCard render snippet: 'debit_card' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 66.
    Payments Example class PaymentMethodPresenter defrender case payment_method when CreditCard render snippet: 'credit_card' when DebitCard render snippet: 'debit_card' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 67.
    Payments Example class PaymentMethodPresenter defrender case payment_method when CreditCard render snippet: 'credit_card' when DebitCard render snippet: 'debit_card' when Instalments render snippet: 'instalments' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 68.
    Payments Example class PaymentMethodPresenter defrender case payment_method when CreditCard render snippet: 'credit_card' when DebitCard render snippet: 'debit_card' when Instalments render snippet: 'instalments' end end end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 69.
    Payments Example # sig/user.rbs typepayment_method = DebitCard | CreditCard | Instalments class User def payment_method: () -> payment_method end # sig/payment_method_presenter.rbs class PaymentMethodPresenter attr_reader payment_method: payment_method def render: () -> String end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 70.
    What about reducingNoMethodError? @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 71.
    Addressable Example Addressable::URI.parse("https://example.com/foo.css?v=123123").query_values => {"v" => "123123" } @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 72.
    Addressable Example version =Addressable::URI.parse(url).query_values['v'] unless version render :bad_request return end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 73.
  • 74.
    Addressable Example class Baddressable definitialize(uri) @uri = uri end def query_values Hash[*URI.parse(@uri).query.split("=")] end end Baddressable.new("https://example.com").query_values['v'] baddressable.rbs: class Baddressable def initialize: (String?) -> void def query_values: -> Hash[String, String]? end @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 75.
    Addressable Example [error] Type`(::Hash[::String, ::String] | nil)` does not have method `[]` │ Diagnostic ID: Ruby::NoMethod │ └ Baddressable.new("https://example.com").query_values['v'] @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 76.
    Takeaways @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/
  • 77.
    Takeaways • Types werealways there; now we're able to work with them more intentionally in Ruby. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 78.
    Takeaways • Types werealways there; now we're able to work with them more intentionally in Ruby. • Using these type checking tools can help us ensure errors really only happen once by making our code a little smarter. @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 79.
    Takeaways • Types werealways there; now we're able to work with them more intentionally in Ruby. • Using these type checking tools can help us ensure errors really only happen once by making our code a little smarter. • It's going to take adoption and use by the community for this feature to be as successful as possible! @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 80.
    Thank you! Sam Doiron@conlectus Fleur de Ruby meetup @fleur_de_ruby Grusp for hosting this event, & you for attending! @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 81.
    Go forth &build with types! @thecodewitch, slides available at thecodewitch.codes/checking-your-types/
  • 82.
    @thecodewitch, slides availableat thecodewitch.codes/checking-your-types/