Sorbet

Sorbet

  • Get started
  • Docs
  • Try
  • Community
  • GitHub
  • Blog

›Experimental Features

Getting Started

  • Overview
  • Adopting Sorbet
  • Tracking Adoption
  • Quick Reference
  • Visual Studio Code
  • TypeScript ↔ Sorbet

Static & Runtime

  • Gradual Type Checking
  • Enabling Static Checks
  • Enabling Runtime Checks
  • RBI Files
  • CLI Quickstart
  • CLI Reference
  • Runtime Configuration

Troubleshooting

  • Troubleshooting
  • Why type annotations?
  • FAQ
  • Error Reference
  • Unsupported Ruby Features

Type System

  • sig
  • Type Annotations (non-sig)
  • T.let, T.cast, T.must, T.bind
  • Class Types (Integer, String)
  • Arrays & Hashes
  • Nilable Types (T.nilable)
  • Union Types (T.any)
  • Flow-Sensitivity (is_a?, nil?)
  • T.type_alias
  • Exhaustiveness (T.absurd)
  • T::Struct
  • T::Enum
  • T.untyped
  • Blocks, Procs, & Lambdas
  • Abstract Classes & Interfaces
  • Final Methods & Classes
  • Override Checking
  • Sealed Classes
  • T.class_of
  • T.self_type
  • T.noreturn
  • T.anything
  • T.attached_class
  • Intersection Types (T.all)
  • Generics
  • T::NonForcingConstants
  • Banning untyped

Editor Features

  • Language Server (LSP)
  • Server Status
  • LSP & Typed Level
  • Go to Definition
  • Hover
  • Autocompletion
  • Find All References
  • Code Actions
  • Outline & Document Symbols
  • Documentation Comments
  • Suggesting sigs
  • Highlighting untyped
  • sorbet: URIs

Experimental Features

  • Tuples
  • Shapes
  • Overloads
  • Requiring Ancestors
  • RBS Comments
Edit

Shapes

TODO: This page is still a fragment. Contributions welcome!

{symbol1: Type1, symbol2: Type2}

{'string1' => Type1, 'string2' => Type2}

This creates a fixed hash type (also referred to as a record), which is a hash with known keys and known types for each key. For example, {foo: String, bar: T.nilable(Float)} validates that an object is a hash with exactly those 2 keys as Ruby symbols, with foo being a String and bar being a Float or nil. For example: {foo: 'hello', bar: 3.14}.

Warning: Shape types have many known limitations, and should be considered an experimental feature. They may not work as expected or change without notice. For an alternative that plays better with static type checking, see Typed Structs.

# typed: true

# Shape types work for some simple cases,
# but have many known limitations.
#
# Consider instead using T::Struct to create a
# data class which models your domain.
#

extend T::Sig

sig {params(x: {a: Integer, b: String}).void}
def foo(x)
  # Limitation! returns T.untyped!
  T.reveal_type(x[:a]) # Revealed type: `T.untyped`

  # Limitation! does not warn when key doesn't exist!
  x[:c]
end

# --- What you expect ---
foo({a: 0,  b: ''}) # ok
foo({a: '', b: 0}) # error: type mismatch
foo({}) # error: missing keys

# --- What you might not expect ---
foo({a: 0, b: '', j: nil}) # ok

# --- Mutation: the ugly ---
y = {a: 0, b: ''}
y[:a] = '' # ok (!)

→ View on sorbet.run

sorbet internals note: the underlying() of a shape is a Hash where the key type is the union of all keys and the value type is the union of all the values.

← TuplesOverloads →

Get started · Docs · Try · Community · Blog · Twitter